Раздел в RecylerView с курсором

Я прочитал много сообщений StackOverflow о такой проблеме, но большинство из них не использовали курсор в качестве источника данных для RecyclerView. Но мое приложение делает.

В моем приложении я запрашиваю базу данных, которая дает мне результаты, как показано на следующем рисунке. Результаты упорядочены по столбцу _id.

введите здесь описание изображения

Я хочу, чтобы мой RecyclerView представлял данные примерно так:

White Blood Cell(WBC)
    52 10^9/L 2018-08-15
    52 10^9/L 2018-08-15
    52 10^9/L 2018-08-15

Red Blood Cell - Male
    52 10^9/L 2018-08-15
    52 10^9/L 2018-08-15
    52 10^9/L 2018-08-15

Как видите, он образует группы с заголовками, и под каждым заголовком находятся соответствующие элементы.

Я создал два разных макета.

Заголовок с элементом под ним

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
    <TextView
        android:id="@+id/heading"" />
    <LinearLayout>
        <TextView
            android:id="@+id/value" />
        <TextView
            android:id="@+id/date" />
    </LinearLayout>
</LinearLayout>

Макет элемента

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
    <TextView
        android:id="@+id/value" />
    <TextView
        android:id="@+id/date"/>
</LinearLayout>

Игнорировать отсутствующие детали в файлах макета

С другой стороны, мой адаптер делает следующее.

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

    // it holds the _id of the last group    
    private int lastGroupId = -1;

    private final int VIEW_TYPE_HEADING = 0, VIEW_TYPE_ITEM = 1;


    @Override
    public int getItemViewType(int position) {
        int returnItemViewType;

        // get _id value for the row at given position
        int currentGroupId = getCursorAtPosition(position).getInt(0);
        if (currentGroupId != lastGroupId) {
            // return VIEW_TYPE_HEADING
            lastGroupId = currentGroupId;
            returnItemViewType = VIEW_TYPE_HEADING;
        } else {
            returnItemViewType = VIEW_TYPE_ITEM;
        }
        return returnItemViewType;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        RecyclerView.ViewHolder viewHolder;
        View view;
        if (viewType == VIEW_TYPE_HEADING) {
            // inflate HEADING LAYOUT
        } else {
            // inflate item layout
        }
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, Cursor cursor, int position) {

        if (viewHolder.getItemViewType() == VIEW_TYPE_HEADING) {
            // bind values to heading layout
        } else {
            // bind values to item layout
        }
    }

    public class HeadingViewHolder extends RecyclerView.ViewHolder {
    }

    public class ItemViewHolder extends RecyclerView.ViewHolder {
    }

}

что я делаю в getItemViewType, так это проверяю, соответствует ли столбец _id значению lastGroupId, используя аргумент позиции, который передается методу. Если он совпадает, я просто возвращаю VIEW_TYPE_ITEM, что является обычным макетом элемента.

И если он не совпадает, то это указывает на то, что это начало другой группы, поэтому в этом случае я возвращаю VIEW_TYPE_HEADING.

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

введите здесь описание изображения

Я точно знаю, что способ, которым я реализовал getViewItemType, неверен , я также знаю, что когда мои вьюхолдеры перерабатываются, это мешает моему методу getViewItem из-за этой переменной lastGroupId.

Можете ли вы дать мне какие-либо предложения, как мне это сделать или что я могу сделать, чтобы добиться таких результатов в RecyclerView с курсором или в чем мои ошибки?


person Ahad    schedule 19.08.2018    source источник
comment
comment
Не могли бы вы показать метод getItemCount адаптера?   -  person Mosius    schedule 19.08.2018
comment
Ну, я просто возвращаю cursor.getCount() для getItemCount()   -  person Ahad    schedule 19.08.2018


Ответы (1)


Проблема возникает, когда вы прокручиваете recyclerView и поэтому lastGroupId не заполняется полностью.

Используйте эту логику вместо вашего текущего кода в getItemViewType:

if (position == 0) {
    return VIEW_TYPE_HEADING;
} else {
    int currentGroupId = getCursorAtPosition(position).getInt(0);
    int previousGroupId= getCursorAtPosition(position - 1).getInt(0);
    return currentGroupId != previousGroupId ? VIEW_TYPE_HEADING : VIEW_TYPE_ITEM;
}
person Mosius    schedule 19.08.2018
comment
Да, и таким образом мне не нужно полагаться на переменную lastGroupId, которая на самом деле не представляет идентификатор последней группы, поскольку RecyclerView выполняет оптимизацию, lastGroupId получает недопустимые значения для элементов. - person Ahad; 19.08.2018