2016-04-25 10 views
1

Ich habe versucht, zu verstehen, wie ich leicht zwei verschiedene Ansichten aufgeblasen werden kann sagen, auf dem Objekt auf einigen Informationen abhängig ...Wie werden mehrere Viewholders in der Recycler-Ansicht angezeigt?

Mein Setup wie so ist, aber ich mit diesem Fehler immer wieder abstürzt:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setTypeface(android.graphics.Typeface)' on a null object reference 

, die auf dieser Linie zeigt:

myViewHolder.commentUsername.setTypeface(boldTypeface); 

Das ist mein Adapter:

public class CommentsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 

    private List<DatabaseComment> dbCommentsList; 
    private DatabaseHelper db; 
    private Context context; 
    private Typeface typeFace, italicTypeface, boldTypeface; 


    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 
     public TextView commentUsername, commentUserMsg, commentUserDate, commentUserRemove; 
     public ImageView emojiIcon; 


     public MyViewHolder(View view) { 
      super(view); 
      commentUsername = (TextView) view.findViewById(R.id.userAdapterUsername); 
      commentUserMsg = (TextView) view.findViewById(R.id.commentUserMsg); 
      commentUserDate = (TextView) view.findViewById(R.id.commentUserDate); 
      commentUserRemove = (TextView) view.findViewById(R.id.commentUserRemove); 
      emojiIcon = (ImageView) view.findViewById(R.id.emojiIcon); 
      Log.d(Constants.DEBUG, "IN MY VIEW HOLDER"); 

      view.setOnClickListener(this); 
      commentUserRemove.setOnClickListener(this); 

     } 

     @Override 
     public void onClick(View v) { 
      if (mOnEntryClickListener != null) { 
       Log.d(Constants.DEBUG, "IN On click"); 
       mOnEntryClickListener.onEntryClick(v, getAdapterPosition()); 

      } 
     } 
    } 
    private static OnEntryClickListener mOnEntryClickListener; 

    public interface OnEntryClickListener { 
     void onEntryClick(View view, int position); 
    } 

    public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) { 
     mOnEntryClickListener = onEntryClickListener; 
    } 


    public class MyFeatureViewHolder extends RecyclerView.ViewHolder { 
     public TextView commentCompany, commentCompanyMsg, commentCompanyDate; 
     public ImageView emojiIcon; 


      public MyFeatureViewHolder(View view) { 
      super(view); 
       commentCompany = (TextView) view.findViewById(R.id.commentCompany); 
       commentCompanyMsg = (TextView) view.findViewById(R.id.commentCompanyMsg); 
       commentCompanyDate = (TextView) view.findViewById(R.id.commentCompanyDate); 
       emojiIcon = (ImageView) view.findViewById(R.id.emojiIcon); 
       Log.d(Constants.DEBUG, "IN MY VIEW HOLDER"); 


     } 


    } 

    public CommentsAdapter(Context mContext, List<DatabaseComment> comments, Typeface myTypeface, Typeface myTypefaceItalic, Typeface myTypefaceBold) { 
     context = mContext; 
     db = new DatabaseHelper(context); 
     dbCommentsList = comments; 
     typeFace = myTypeface; 
     italicTypeface = myTypefaceItalic; 
     boldTypeface = myTypefaceBold; 
    } 

    @Override 
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     switch (viewType){ 
      case 0: 
       return new MyFeatureViewHolder(LayoutInflater.from(parent.getContext()) 
         .inflate(R.layout.comment_business_item, parent, false)); 
      case 1: 
       return new MyFeatureViewHolder(LayoutInflater.from(parent.getContext()) 
         .inflate(R.layout.comment_user_item, parent, false)); 
     } 
     return new MyViewHolder(LayoutInflater.from(parent.getContext()) 
       .inflate(R.layout.comment_user_item, parent, false)); 


    } 



    @Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 

     //int pos = getItemViewType(position); 

     //is a business comment 
     if(dbCommentsList.get(position).getIsType() == 0) { 


      MyFeatureViewHolder featureViewHolder = (MyFeatureViewHolder) holder; 

      DatabaseComment dbComment = dbCommentsList.get(position); 

      featureViewHolder.commentCompany.setTypeface(boldTypeface); 
      featureViewHolder.commentCompanyMsg.setTypeface(typeFace); 
      featureViewHolder.commentCompanyDate.setTypeface(italicTypeface); 

      featureViewHolder.commentCompany.setText(dbComment.getUsername()); 
      featureViewHolder.commentCompanyMsg.setText(dbComment.getCommentText()); 

      Calendar date = Calendar.getInstance(); 
      date.setTimeInMillis(dbComment.getCommentDate()); 
      String commentDateTxt = (date.get(Calendar.MONTH) + "." + date.get(Calendar.DAY_OF_MONTH) + "." + date.get(Calendar.YEAR)); 

      featureViewHolder.commentCompanyDate.setText(commentDateTxt); 


      //anything greater than 0 is a user comment 
     } else { 
      //TODO show x button near viewHolder if isChanged is 1 

      MyViewHolder myViewHolder = (MyViewHolder) holder; 

      if(dbCommentsList.get(position).getIsChanged() == 1) { 
       myViewHolder.commentUserRemove.setVisibility(View.VISIBLE); 
      } else { 
       myViewHolder.commentUserRemove.setVisibility(View.GONE); 
      } 

      DatabaseComment dbComment = dbCommentsList.get(position); 

      myViewHolder.commentUsername.setTypeface(boldTypeface); 
      myViewHolder.commentUserMsg.setTypeface(typeFace); 
      myViewHolder.commentUserDate.setTypeface(italicTypeface); 

      myViewHolder.commentUsername.setText(dbComment.getUsername()); 
      myViewHolder.commentUserMsg.setText(dbComment.getCommentText()); 

      Calendar date = Calendar.getInstance(); 
      date.setTimeInMillis(dbComment.getCommentDate()); 
      String commentDateTxt = (date.get(Calendar.MONTH) + "." + date.get(Calendar.DAY_OF_MONTH) + "." + date.get(Calendar.YEAR)); 

      myViewHolder.commentUserDate.setText(commentDateTxt); 

      int[] commentsImageList = new int[]{R.drawable.ic_announcement_black_18dp, R.drawable.ic_announcement_black_18dp, R.drawable.ic_announcement_black_18dp, R.drawable.ic_explore_black_18dp}; 
      myViewHolder.emojiIcon.setImageResource(commentsImageList[dbComment.getIsType()]); 



     } 

     //grab more comments 
     if(position > (dbCommentsList.size() - 3) && (dbCommentsList.size() % 20) == 0) { 
      grabMoreComments(); 
     } 

    } 

    private void grabMoreComments() { 
     //TODO 
     //GRABAPI - OFFSET dbCommentsList.SIZE - IN LIMIT OF 20 
    } 



    @Override 
    public int getItemCount() { 
     return dbCommentsList.size(); 
    } 



    @Override 
    public int getItemViewType(int position) { 
     if(dbCommentsList.get(position).getIsType() == 0) { 
      return 0; 
     } 
     return 1; 
    } 
} 

Das ist meine Klasse, wo ich ein Setup der Adapter:

private void setupAdapter() { 
     commentsAdapter = new CommentsAdapter(this, dbCommentsList, TypeFaceProvider.getTypeFace(this, 0), 
       TypeFaceProvider.getTypeFace(this, 1), TypeFaceProvider.getTypeFace(this, 2)); 
     RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext()); 
     commentsRecyclerView.setLayoutManager(mLayoutManager); 
     commentsRecyclerView.setItemAnimator(new DefaultItemAnimator()); 

     //TODO CHECK THAT CLICKING ON COMMENT BY BUSINESS NOTHING HAPPENS 

     commentsAdapter.setOnEntryClickListener(new CommentsAdapter.OnEntryClickListener() { 
      @Override 
      public void onEntryClick(View view, int position) { 
       DatabaseComment comment = dbCommentsList.get(position); 
       TextView deleteBtn = (TextView) view.findViewById(R.id.commentUserRemove); 
       if(view == deleteBtn) { 

        //used to remove the comment from db and the list 
        db.removeSingleComment(comment); 
        dbCommentsList.remove(position); 
        commentsAdapter.notifyDataSetChanged(); 

       } else { 
        Toast.makeText(getApplicationContext(), comment.getUsername() + " is selected!", Toast.LENGTH_SHORT).show(); 
        takeToUserProfile(dbCommentsList.get(position)); 
       } 
      } 
     }); 




     commentsRecyclerView.setAdapter(commentsAdapter); 

     commentsAdapter.notifyDataSetChanged(); 

    } 

So im Adapter getItemViewType nicht richtig gemacht wird ... wie soll ich sagen, wenn die Kommentare isType 0 ist eine Ansicht und alle andere Show zu zeigen, die andere Ansicht?

+1

prüfen ... zurück myViewHolder wenn die getViewType() 1 zurück. Überprüfen Sie später, ob die Instanz des Halters myViewHolder ist oder nicht wie if (holder instanceOf MyViewHolder), und aktualisieren Sie dann die Ansichten. –

+0

Was meinst du mit case: 1, ich dachte, der Standard wird es zurückgeben, ich versuchte mit case: 1 obwohl auch und es zeigt immer noch einen Fehler – Lion789

+1

das ist in Ordnung, überprüfen Sie die Inhaberinstanz in onBindViewHolder(). –

Antwort

1

Basierend auf dem Fehler sieht es wie eine Ansicht mit der ID R.id.userAdapterUsername wird in der Layout-Datei comment_user_item.xml fehlt die Bedingung in Schalter

+0

Ich benutze die falsche ID vergessen, es zu ändern, nicht realisiert, danke! – Lion789

3

Zuerst müssen Sie getItemViewType Ihren Adapters wie unten außer Kraft zu setzen: (Ich gehe davon aus Sie Ihre viewholders mit Ihrem Objekt getType() Methode entsprechen können.)

@Override 
    public int getItemViewType(int position) { 
     return items.get(position).getType(); 
    } 

Und in Ihrem onCreateViewHolder Switch-Typ Verfahren und senden Sie Ihre zugehörigen viewholder .

 @Override 
     public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
      View view = null; 
      switch (viewType) { 
       case ITEM_TYPE_A: 
        view = mInflater.inflate(R.layout.your_row_a, parent, false); 
        return new ATypeViewHolder(view); 

       case ITEM_TYPE_B: 
        view = mInflater.inflate(R.layout.your_row_b, parent, false); 
        return new BTypeViewHolder(view); 
    } 
} 

INIT Ihre onBindViewHolder Methode des Adapters.

@Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     Item item = items.get(position); 
     if(item != null){ 
       initializeViews(item, holder, position); 
     } 
} 

schließlich in Ihrem initializeViews Verfahren werfen Sie Ihre viewholder nach Ihrem Artikeltyp und verwendet es:

private void initializeViews(final Item item, final RecyclerView.ViewHolder viewHolder, final int position) { 
    swtich(item.gettype()) 
    { 
     case ITEM_TYPE_A: 
      ATypeViewHolder holder = (ATYpeViewHolder)viewHolder; 
      // init your views 

     case ITEM_TYPE_B: 
      BTypeViewHolder holder = (BTypeViewHolder)viewHolder; 
      // init your views. 
    } 
} 

nicht: Ihre viewholders RecyclerView.ViewHolder verlängern müssen

Ich hoffe, das Ihnen helfen wird. Viel Glück.

+0

oh es tut mir leid es ist meine private benutzerdefinierte Methode. Sie sollten es in OnBindViewHolder-Methode aufrufen. Ich habe meinen Beitrag bearbeitet. – savepopulation

+0

Ich sehe die Methoden, die Sie haben, aber das ändert nichts an dem, was ich in meinem eigenen Code mache. Sie fügen einfach eine andere Methode außerhalb des onBindViewHolders hinzu, die ich bereits in diesem Code verwende. – Lion789

+0

Außerdem kann isType auf dem Element 0 oder größer als 0 sein ... deshalb muss ich sehen, ob es 0 ist, wenn nicht 1 zurückgegeben wird (weil der isType 0,1,2,3,4, etc sein kann ...) aber größer als 0 sollte eine andere Sicht aufblasen. – Lion789