web-dev-qa-db-ja.com

Recyclerview +コンテンツプロバイダー+ CursorLoader

SQLiteデータベースにいくつかのデータがあります。データベースからデータを取得するコンテンツプロバイダーがあります。問題は、cursorLoaderを実装してrecyclerviewと連携する方法です。

また、カーソルから直接ではなく、リストビュー/リサイクラービューに表示するために、カーソルからオブジェクトにデータを転送する必要がある理由を誰でも説明できますか?

たとえば、カスタムcursorAdapterクラスでは、

Person person = new Person(cursor.getString(cursor.getColumnIndexOrThrow(PERSON_NAME)));
textview.setText = person.getName();

OR

textview.setText = cursor.getString(cursor.getColumnIndexOrThrow(PERSON_NAME));

上記の方法のどれが良いですか?

以前はリストビューとグリッドビューがありましたが、現在はそれらを組み合わせてリサイクラービューになっているようです。次に、グリッドベースのrecyclerviewを実装するにはどうすればよいですか?

20
Abdul Rahman

一般に、ビューとデータの責任を分離するようにしてください。したがって、必要なのは、事前にデータベースからすべてのオブジェクトを取得してから、次のようなアダプタを設定することです。

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
    private final List<Person> objectList = new ArrayList<>();

    @Override
    public CustomAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
        final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        return new ViewHolder(layoutInflater.inflate(R.layout.adapter_item, parent, false));
    }

    @Override
    public void onBindViewHolder(final CustomAdapter.ViewHolder holder, final int position) {
        holder.bindItem(objectList.get(position));
    }

    // Set the persons for your adapter
    public void setItems(final List<Person> persons) {
        objectList.addAll(persons);
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        return objectList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView mTextViewTitle;
        private Object mObject;

        public ViewHolder(final View itemView) {
            super(itemView);
            mTextViewTitle = (TextView) itemView.findViewById(R.id.view_item_textViewTitle);                
            mTextViewTitle.setText(mObject.getText());
        }

        private void bindItem(@NonNull final Person object) {
            mObject = object;
        }
    }
}

次に、次の方法でアダプタをRecyclerViewにバインドできます。

final CustomAdapter adapter = new CustomAdapter();
adapter.setItems(mPersons);
mRecyclerView.setAdapter();

2番目の質問に答えるには(「以前はリストビューとグリッドビューがありましたが、現在はそれらが組み合わされてリサイクラービューになっているようです。次に、グリッドベースのリサイクラービューを実装するにはどうすればよいですか?」):

LayoutManagerをRecyclerViewにバインドするときに、どちらを使用するかを決定できます。

final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);

または

final GridLayoutManager layoutManager = new GridLayoutManager(this, COLUMN_SPAN_COUNT);
mRecyclerView.setLayoutManager(layoutManager);

いくつかのLayoutManagerがあります。詳細 ここ

更新:事前にすべてのアイテムをロードする必要はありません。setItemsの名前をaddItemsに変更するだけで、準備は完了です。

4
luckyhandler

thisthis のようなGithubの要点/プロジェクトがいくつかあり、そのようなユースケースを示しています。

カーソルアダプタに合わせてカスタマイズされたアダプタを使用する場合は、通常どおりGridLayoutManager/LinearLayoutManagerを使用します。

3
Droidekas

カスタムCursorAdapter for RecyclerViewを直接使用できると思うので、カーソルをに変換する必要はありません。 ArrayList

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

    // Because RecyclerView.Adapter in its current form doesn't natively 
    // support cursors, we wrap a CursorAdapter that will do all the job
    // for us.
    CursorAdapter mCursorAdapter;

    Activity mContext;
    Random rnd;

    public ProductListAdapter(AppCompatActivity context, Cursor c) {

        mContext = context;
        rnd = new Random();

        mCursorAdapter = new CursorAdapter(mContext, c, 0) {

            @Override
            public View newView(Context context, Cursor cursor, ViewGroup parent) {
                // Inflate the view here
                LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
                return inflater.inflate(R.layout.row_product_layout_grid, parent, false);
            }

            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                String productName = cursor.getString(cursor.getColumnIndex(TProduct.PRODUCT_NAME));

                // Binding operations
                ((TextView) view.findViewById(R.id.sub_product_name_text_view)).setText(productName);



                int color = Color.argb(200, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));

                String url = "http://dummyimage.com/300/" + color + "/ffffff&text=" + (cursor.getPosition() + 1);

                Picasso
                        .with(context)
                        .load(url)
                        .placeholder(R.mipmap.ic_launcher) // can also be a drawable
                        .into((ImageView) view.findViewById(R.id.sub_product_image_view));
            }
        };
    }

    public void reQuery(Cursor c) {
        if (mCursorAdapter != null) {
            mCursorAdapter.changeCursor(c);
            mCursorAdapter.notifyDataSetChanged();
        }
    }

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

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // Passing the binding operation to cursor loader
        mCursorAdapter.getCursor().moveToPosition(position); //EDITED: added this line as suggested in the comments below, thanks :)
        mCursorAdapter.bindView(holder.view, mContext, mCursorAdapter.getCursor());
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // Passing the inflater job to the cursor-adapter
        View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
        return new ViewHolder(v);
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        View view;
        public ViewHolder(View itemView) {
            super(itemView);
            view = itemView.findViewById(R.id.product_row_card_view);
        }
    }
}

それがあなたに役立つように。 :)

1
Pratik Butani