Recyclerview: использование нескольких типов просмотра и настройка видимости для разных макетов

Я использую представление переработчика в приложении чата, теперь, как вы все знаете в чате, у нас есть 2 разных представления.

Вид справа: тот, который вы отправили.

Вид слева: тот, который вы получили.

Теперь мне удалось добиться того, что я хочу, используя один элемент макета, и внутри этого элемента я использовал 2 относительных макета, один макет для правого вида и другой для левого вида.

И чтобы узнать, какой макет показать, я сделал это в 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);
    }
}

У меня нет проблем с использованием вышеуказанного метода. Но мой вопрос заключается в том, почему другие используют ту вещь, которая называется несколькими типами представлений, в которой они используют 2 держателя представлений? Я должен использовать это вместо этого?

2 ответа

Решение

Первое: в вашем случае я не уверен, действительно ли необходимо использовать два типа представлений. Типичный RecyclerView на мобильном телефоне будет отображаться от семи до десяти строк одновременно, и он будет генерировать еще несколько, чтобы иметь возможность плавно прокручивать в случае необходимости. По сравнению с игровым приложением практически ничего не нужно делать с точки зрения пользовательского интерфейса. Но вы спросили, почему кто-то может захотеть использовать несколько типов представлений, так что здесь идет:

Прямо сейчас 50% Views вы будете раздувать будет установлен GONEТаким образом, это похоже на непрерывную трату процессорного времени и (что еще хуже на мобильном устройстве) разряжает батарею без необходимости. Используя два типа представлений, вы избегаете этого (в некоторой степени, я полагаю, что определение типа представления требует меньше энергии).

Другая причина - лучшая производительность, которая приводит к лучшему восприятию пользователя: RecyclerView был разработан для эффективной работы со списками предметов. Сообщая ему, какую строку можно повторно использовать для какой позиции списка, вы наилучшим образом используете его алгоритм повторного использования.

С точки зрения разработчика, я бы придерживался вашего подхода, если разница между этими двумя типами составляет не более двух или трех строк кода. Но есть списки, где разница больше похожа на двадцать строк кода. В этом случае используются разные типы представлений, файлы макетов и ViewHolders улучшает читабельность вашего кода.

Да, вы должны реализовать разные ViewHolder для каждого типа зрения. Это обеспечивает несколько преимуществ, таких как отсутствие необходимости поддерживать соответствующее состояние, упорядочение макетов и, как правило, упрощение рассуждений о том, что в будущем будет добавлена ​​дополнительная функциональность.

Это также легко реализовать:

@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;                                            
}

затем:

@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:                                                                    
            // ...                                                               
    }                                                                                                                                                                                                                                                                   
} 

в конце концов:

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

    switch (getItemViewType(position)) {                                                         
        case VIEWTYPE_RECEIEVED:
        // ...
    }
} 
Другие вопросы по тегам