2

I am using recycler view in a chat app, now as you all know in a chat room we have 2 different views.

Right view : the one that you sent.

Left view : the one that you received.

Now I managed to achieve what I want by using one layout item and inside that item I used 2 relative layouts, one layout for the right view and another for the left view.

And in order to know what layout to show I did this in onBindViewholder:

onBindViewHolder(){
    if(/*I sent the message*/){
        right_layout.setVisibility(view.VISIBLE);
        left_layout.setVisibility(view.GONE);  
    }
    else {
        right_layout.setVisibility(view.GONE);
        left_layout.setVisibility(view.VISIBLE);
    }
}

I don't have any problem with using the above method. But my question is why others use that thing that is called multiple view types in which they use 2 view holders? Should I use it instead?

user1506104
  • 6,554
  • 4
  • 71
  • 89
Hasan Bou Taam
  • 4,017
  • 2
  • 12
  • 22

2 Answers2

4

First: in your case, I'm not sure whether it's really necessary to use two view types. A typical RecyclerView on a mobile phone will show between seven and ten rows at a time and it will generate some more just to be able to scroll smoothly should the need arise. Compared to a gaming app, there's next to nothing to do UI-wise. But you asked why someone might want to use multiple view types, so here goes:

Right now 50% of the Views you're inflating will be set to GONE, so it's like a continous waste of CPU time and (worse on a mobile device) it's draining the battery unnecessarily. By using two view types, you avoid this (to a certain extent, I suppose that determining the view type takes less energy).

Another reason is better performance which results in a better user experience: RecyclerView was developed to efficiently deal with lists of items. By telling it which row can be reused for which list position, you are making the best use of its recycling algorithm.

From a developer point of view, I'd keep your approach as long as the difference between the two types is no more than two or three lines of code. But there are lists where the difference is more like twenty lines of code. In this case, using different view types, layout files and ViewHolders improves the readability of your code.

Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61
  • I use one item view that has too many nested relative layouts, one for right message, one for left message, another for the date between the messages...What do you think in this case? – Hasan Bou Taam Mar 30 '18 at 18:08
  • @svi.data - in this case I'd prefer two view types. It's easier to develop, easier to maintain and I expect it to be easier on the battery too. – Bö macht Blau Mar 30 '18 at 18:11
  • In other words does the complexity of the layout item of the recyclerview affect its scrolling? – Hasan Bou Taam Mar 30 '18 at 18:14
  • @svi.data - I think it does: every time you scroll, the RecyclerView will call onCreateViewHolder if it needs additional Views of a certain type. If it has some in cache (because they are no longer attached to the window and can be recycled) then it will only call onBindViewHolder. In this case you would not have to toggle visibility (which means recalculating the layout) but just fill in your data. This would be better for performance – Bö macht Blau Mar 30 '18 at 18:15
  • @svi.data - "does the complexity of the layout item of the recyclerview affect its scrolling" most certainly yes, as soon as it comes to drawing which happens while scrolling – Bö macht Blau Mar 30 '18 at 18:16
2

Yes, you should implement different a ViewHolder for each type of view. This provides a few advantages, like not having to maintain the relevant state, decluttering layouts, and generally easier to reason about once additionally functionality is included in the future.

It's also easy to implement:

@Override                                                
public int getItemViewType(int position) {               
    Message message = messages.get(position);                    
    if (message instanceof ReceivedMessage) {
        return VIEWTYPE_RECEIVED;                                                                                                                    
    }                                                    
    if (message instanceof SentMessage) {                    
        return VIEWTYPE_SENT;                          
    }                                                    
    return 0;                                            
}

then:

@Override                                                                                        
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {              
    LayoutInflater inflater = LayoutInflater.from(mContext);                                     
    switch (viewType) {                                                                          
        case VIEWTYPE_RECEIVED:                                                                                                                    
            View receivedView = inflater.inflate(R.layout.item_received, parent, false);           
            ReceivedViewHolder receivedViewHolder = new ReceivedViewHolder(receivedView);            
            return receievedViewHolder;                                                            
        case VIEWTYPE_SENT:                                                                    
            // ...                                                               
    }                                                                                                                                                                                                                                                                   
} 

finally:

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

    switch (getItemViewType(position)) {                                                         
        case VIEWTYPE_RECEIEVED:
        // ...
    }
} 
Orbit
  • 2,985
  • 9
  • 49
  • 106