Как сделать адаптер для SQLite для RecyclerView?

Нашел готовое решение, и очень интересно его краткое объяснение, т.к. не до конца его понимаю. Почему мой код работает с тормозами а тот что в решении не должен. Дело в том где я расположен код переноса элементов в массив? Или именно из-за переноса он и работает медленно? Метод onBindViewHolder вызывается при появлении на экране нового представления, т.е. код оттуда выполняется постепенно: вначале появляется представление, выполняется код, затем следующее и тд?

Самый волнующий вопрос как исправить именно мой код, чтобы он работал нормально?

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

    private Listener mListener;
    private Cursor mCursor;

    interface Listener {
        void onClick(int position);
    }

    public void setListener(Listener mListener){
        this.mListener = mListener;
    }

    public TaskAdapter (Cursor cursor){
        mCursor = cursor;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        private CardView mCardView;

        public ViewHolder(CardView v){
            super(v);
            mCardView = v;
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        CardView cardView = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.card_task, parent, false);
        return new ViewHolder(cardView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder,final int position) {
        if (mCursor != null){

            ArrayList<String> titles = new ArrayList<String>();
            ArrayList<String> descriptions = new ArrayList<String>();
            ArrayList<Integer> imageIds = new ArrayList<Integer>();

            mCursor.moveToFirst();
            while (!mCursor.isAfterLast()){
                titles.add(mCursor.getString(0));
                descriptions.add(mCursor.getString(1));
                imageIds.add(mCursor.getInt(2));
                mCursor.moveToNext();
            }

            CardView cardView = holder.mCardView;

            ImageView imageView = cardView.findViewById(R.id.task_image);
            Drawable drawable = ContextCompat.getDrawable(cardView.getContext(), imageIds.get(position));
            imageView.setImageDrawable(drawable);

            TextView titleView = cardView.findViewById(R.id.task_title);
            titleView.setText(titles.get(position));

            TextView descriptionView = cardView.findViewById(R.id.task_description);
            descriptionView.setText(descriptions.get(position));

            cardView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (mListener != null) {
                        mListener.onClick(position);
                    }
                }
            });
        }
    }

    @Override
    public int getItemCount(){
        return mCursor.getCount();
    }

}

Ответы (1 шт):

Автор решения: Sergei Buvaka

Ваш адаптер не должен знать нечего о всяких SQLite и любых других подобных вещах.

По хорошему адаптер должен уметь только рисовать список который вы ему дали. Он не должен ходить в базу, в сеть или куда бы то ни было ещё. Это не его ответственность.

У вас должна быть сущность типа Presenter/ViewModel которая загрузит и подготовит данные для адаптера. И сделать она это должна не на UI потоке. Когда она это сделает она должна передать в адаптер уже готовый список данных.

В противном случае у вас будут лаги в интерфейсе, потому что адаптер будет делать запросы в БД на UI потоке.

→ Ссылка