Risa
Risa

Reputation: 63

Recyclerview adapter with CursorAdapter

I'm trying to implement an adapter for a Recyclerview with the use of CusrorAdapter as below as suggested in the one of the solutions here.

I am new to Android and I don't quite know how I should override CursorAdapter's newView method and bindView method. Also I am guessing that mine adapter will have multiple variables in ViewHolder instead of one (View v1) as there are several textViews in my layout file, but I just don't know how they all fit in in the code.

public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder {

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

public MyRecyclerAdapter(Context context, Cursor c) {
    mContext = context;
    mCursorAdapter = new CursorAdapter(mContext, c, 0) {

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            // Inflate the view here
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            // Binding operations

        }
    };
}

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

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

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    // Passing the binding operation to cursor loader
    mCursorAdapter.bindView(holder.itemView, 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);
    }
}

Upvotes: 3

Views: 4436

Answers (2)

Risa
Risa

Reputation: 63

Somehow I managed to get it working although I don't understand how it works in details. Basically I added a ViewHolder variable as a class variable and change some parts of the code. The solution looks something like this when you have 2 TextView items (name and date) in your layout file called row.xml:

public class MyRecyclerAdapter extends Adapter<MyRecyclerAdapter.ViewHolder>{

    // PATCH: Because RecyclerView.Adapter in its current form doesn't natively support
    // cursors, we "wrap" a CursorAdapter that will do all teh job for us
    private CursorAdapter mCursorAdapter;
    private Context mContext;
    private ViewHolder holder;

    public MyRecyclerAdapter(Context context, Cursor c) {
        mContext = context;
        mCursorAdapter = new CursorAdapter(mContext, c, 0) {

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

            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                // Binding operations
                String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
                String date = cursor.getString(cursor.getColumnIndexOrThrow("date"));

                holder.tvName.setText(name);
                holder.tvDate.setText(date);
            }
        };
    }

    public static class ViewHolder extends RecyclerView.ViewHolder{
        public TextView tvName;
        public TextView tvDate;

        public ViewHolder(View itemView) {
            super(itemView);
            tvName = (TextView) itemView.findViewById(R.id.name);
            tvDate = (TextView) itemView.findViewById(R.id.date);
        }
    }

    @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);
        mCursorAdapter.bindView(holder.itemView, 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);
        holder = new ViewHolder(v);
        return holder;
    }
}

If anyone knows why it works, please feel free to join in the discussion. Thanks.

Upvotes: 2

vjsantojaca
vjsantojaca

Reputation: 325

Instead of you create a ViewHolder with a View, you should create the ViewHolder with all the objects you have on the layout (all the elements you need). The layout view must be created (inflate) in method onCreateViewHolder.

Something like that:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
    class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView1;
        TextView textView2;

        public ViewHolder(View itemView) {
            super(itemView);
            textView1 = (TextView) itemView.findViewById(R.id.textView1);
            textView2 = (TextView) itemView.findViewById(R.id.textView2);
        }

        public void insertView(String result1, String result2) {
            textView1.setText(result1);
            textView2.setText(result2);
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_name, parent, false);
        RecyclerView.ViewHolder viewHolder = new ViewHolder(itemView);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((ViewHolder) holder).insertView(results.get(position).getResult1(), results.get(position).getResult2());
    }

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

I think this can help you

You can use a ORMSugar for persistence. Still, if you have the possibility of access to the database outside the adapter it would be much better. You will get the necessary information from the database and pass that information to the adapter constructor.

If you need an example, just you have to tell me.

Upvotes: 0

Related Questions