Статьи

Android RecyclerView

RecyclerView — один из двух виджетов пользовательского интерфейса, представленных библиотекой поддержки в Android L. В этой статье я опишу, как мы можем его использовать и в чем разница между этим виджетом и «классическим» ListView.

Этот новый виджет более гибкий, чем ListView, но он вводит некоторые сложности. По мере использования RecyclerView представляет новый адаптер, который необходимо использовать для представления базовых данных в виджете. Этот новый адаптер называется RecyclerView.Adapter. Чтобы использовать этот виджет, вы должны добавить последнюю версию библиотеки поддержки v7.

Вступление

Мы уже знаем, что в ListView для повышения производительности мы должны использовать шаблон ViewHolder . Это просто Java-класс, который содержит ссылки на виджет в макете строки ListView (например, TextView, ImageView и т. Д.). Используя этот шаблон, мы избегаем вызова метода findById несколько раз, чтобы получить ссылку на виджет пользовательского интерфейса, что делает прокрутку ListView более плавной. Даже если бы этот шаблон был рекомендован как лучший, мы могли бы реализовать наш адаптер без использования этого шаблона.

RecyclerView применяет этот шаблон, делая его ядром этого виджета пользовательского интерфейса, и мы должны использовать его в нашем адаптере.

Адаптер: RecyclerView.Adapter

Если мы хотим показать информацию в ListView или в новом RecyclerView мы должны использовать адаптер. Этот компонент поддерживает виджет пользовательского интерфейса и определяет, как должны отображаться строки в ListView и какую информацию показывать. Также в RecyclerView мы должны использовать адаптер:

1
2
3
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyHolder> {
    ....
}

где MyHolder — наша реализация шаблона ViewHolder. Мы можем предположить, что у нас есть простой макет строки в нашем RecyclerView:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/txt1"/>
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/txt2"/>
 
</LinearLayout>

поэтому наша реализация шаблона ViewHolder:

01
02
03
04
05
06
07
08
09
10
public static class MyHolder extends RecyclerView.ViewHolder {
    protected TextView txt1;
    protected TextView txt2;
 
    private MyHolder(View v) {
        super(v);
        this.txt1 = (TextView) v.findViewById(R.id.txt1);
        this.txt2 = (TextView) v.findViewById(R.id.txt2);
    }
}

Как вы можете заметить, процесс поиска ( findViewById ) выполняется в держателе представления, а не в методе getView.

Теперь мы должны реализовать в нашем адаптере какой-то важный метод, чтобы он работал правильно. Есть два важных метода, которые мы должны переопределить:

  • onCreateViewHolder(ViewGroup viewGroup, int i)
  • onBindViewHolder(MyHolder myHolder, int i)

OnCreateViewHolder вызывается всякий раз, когда должен быть создан новый экземпляр класса View Holder, поэтому этот метод становится:

1
2
3
4
5
6
7
8
@Override
public MyHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    numCreated++;
    Log.d("RV", "OncreateViewHolder ["+numCreated+"]");
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, null);
    MyHolder mh = new MyHolder(v);
    return mh;
}

как вы можете заметить, метод возвращает экземпляр нашей реализации держателя представления, тогда как второй метод вызывается, когда SO связывает представление с данными, поэтому мы устанавливаем содержимое виджета пользовательского интерфейса в значения данных:

1
2
3
4
5
6
7
@Override
public void onBindViewHolder(MyHolder myHolder, int i) {
    Log.d("RV", "OnBindViewHolder");
    Item item = itemList.get(i);
    myHolder.txt1.setText(item.name);
    myHolder.txt2.setText(item.descr);
}

Обратите внимание, что мы не выполняем поиск, а просто используем ссылку на виджет пользовательского интерфейса, хранящуюся в нашем держателе вида

RecyclerView

Теперь у нас есть наш адаптер, мы можем создать наш RecyclerView:

1
2
3
4
RecyclerView rv = (RecyclerView) findViewById(R.id.my_recycler_view);
rv.setLayoutManager(new LinearLayoutManager(this));
MyRecyclerAdapter adapter = new MyRecyclerAdapter(createList());
rv.setAdapter(adapter);

LinearLayoutManager — это «главный» менеджер макетов, используемый для размещения элементов внутри RecyclerView. Мы можем расширить или реализовать наш менеджер раскладок.

Заключительные соображения

Запустив пример, мы получим:

android_recyclerview [4]

Наиболее интересным аспектом является то, сколько раз вызывается onCreateViewHolder по сравнению с количеством отображаемых элементов. Если вы посмотрите на журнал, то увидите, что созданный объект составляет 1/3 от общего числа отображаемых объектов.

Ссылка: Android RecyclerПросмотр нашего партнера JCG Франческо Аццолы в блоге Surviving с Android .