Satyajeet
Satyajeet

Reputation: 99

Android Recyclerview Onclicklistener not working with Cursor

I am working on a project which include Recyclerview and Cursorloader and when user clicks on an item in recyclerview it should get the data from item and start new Activity.But instead it is giving me an exception Attempt to invoke interface method 'boolean android.database.Cursor.moveToPosition(int)' on a null object reference

My Adapter :

public class Mainrow_Adapter extends CursorRecyclerViewAdapter<Mainrow_Adapter.ViewHolder>
{
    Context context;
    Cursor cursor;
     public Mainrow_Adapter(Context context, Cursor cursor)
    {
        super(context, cursor);
        this.cursor = cursor;
        this.context = context;
    }
    @Override
    public Mainrow_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.mainrow_layout,parent,false);
        ViewHolder viewHolder = new ViewHolder(view,context,cursor);
        return viewHolder;
    }
    @Override
    public void onBindViewHolder(Mainrow_Adapter.ViewHolder viewHolder, final Cursor cursor)
    {
        PersonDetails personDetails = PersonDetails.from(cursor);
        AddLog addLog = new AddLog();
        viewHolder.mName.setText(personDetails.getName());
        NumberFormat currency = addLog.changeamount();
        viewHolder.mAmount.setText(currency.format(personDetails.getAmount()));
    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements  View.OnClickListener
    {
        TextView mName,mAmount;

        Context context;
        Cursor cursor;
        public ViewHolder(View itemView,Context context,Cursor cursor) {
            super(itemView);
            this.context = context;
            this.cursor = cursor;
            itemView.setOnClickListener(this);
            mName = (TextView)itemView.findViewById(R.id.mainrowname);
            mAmount = (TextView)itemView.findViewById(R.id.mainrowAmount);
        }

        @Override
        public void onClick(View view) {
            int position = this.getAdapterPosition();
            cursor.moveToPosition(position);
            String name = cursor.getString(1);String mobile = cursor.getString(2);
            String city = cursor.getString(3);String amount = cursor.getString(5);
            Intent intent = new Intent(context,ViewLog.class);
            intent.putExtra("Name",name);intent.putExtra("Mobile",mobile);
            intent.putExtra("City",city);intent.putExtra("Amount",amount);
            context.startActivity(intent);
            Toast.makeText(context,String.valueOf(position), Toast.LENGTH_SHORT).show();
        }
    }
}

Cursor Adapter :

    public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {

        private Context mContext;

        private Cursor mCursor;

        private boolean mDataValid;

        private int mRowIdColumn;

        private DataSetObserver mDataSetObserver;

        public CursorRecyclerViewAdapter(Context context, Cursor cursor) {
            mContext = context;
            mCursor = cursor;
            mDataValid = cursor != null;
            mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1;
            mDataSetObserver = new NotifyingDataSetObserver();
            if (mCursor != null) {
                mCursor.registerDataSetObserver(mDataSetObserver);
            }
        }

        public Cursor getCursor() {
            return mCursor;
        }

        @Override
        public int getItemCount() {
            if (mDataValid && mCursor != null) {
                return mCursor.getCount();
            }
            return 0;
        }

        @Override
        public long getItemId(int position) {
            if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
                return mCursor.getLong(mRowIdColumn);
            }
            return 0;
        }

        @Override
        public void setHasStableIds(boolean hasStableIds) {
            super.setHasStableIds(true);
        }

        public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);

        @Override
        public void onBindViewHolder(VH viewHolder, int position) {
            if (!mDataValid) {
                throw new IllegalStateException("this should only be called when the cursor is valid");
            }
            if (!mCursor.moveToPosition(position)) {
                throw new IllegalStateException("couldn't move cursor to position " + position);
            }
            onBindViewHolder(viewHolder, mCursor);
        }

        /**
         * Change the underlying cursor to a new cursor. If there is an existing cursor it will be
         * closed.
         */
        public void changeCursor(Cursor cursor) {
            Cursor old = swapCursor(cursor);
            if (old != null) {
                old.close();
            }
        }

        /**
         * Swap in a new Cursor, returning the old Cursor.  Unlike
         * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
         * closed.
         */
        public Cursor swapCursor(Cursor newCursor) {
            if (newCursor == mCursor) {
                return null;
            }
            final Cursor oldCursor = mCursor;
            if (oldCursor != null && mDataSetObserver != null) {
                oldCursor.unregisterDataSetObserver(mDataSetObserver);
            }
            mCursor = newCursor;
            if (mCursor != null) {
                if (mDataSetObserver != null) {
                    mCursor.registerDataSetObserver(mDataSetObserver);
                }
                mRowIdColumn = newCursor.getColumnIndexOrThrow("_id");
                mDataValid = true;
                notifyDataSetChanged();
            } else {
                mRowIdColumn = -1;
                mDataValid = false;
                notifyDataSetChanged();
                //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
            }
            return oldCursor;
        }

        private class NotifyingDataSetObserver extends DataSetObserver {
            @Override
            public void onChanged() {
                super.onChanged();
                mDataValid = true;
                notifyDataSetChanged();
            }

            @Override
            public void onInvalidated() {
                super.onInvalidated();
                mDataValid = false;
                notifyDataSetChanged();
                //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
            }
        }

}

i would really appreciate if any of you guys Know a better solution than this to initiate an onclicklistenter and get the Cursor at Items position.

Thank you

Upvotes: 2

Views: 634

Answers (1)

Abanoub Samaan
Abanoub Samaan

Reputation: 226

You don't set the cursor to your viewHolder just set in on onBindViewHolder method

@Override
public void onBindViewHolder(Mainrow_Adapter.ViewHolder viewHolder, final Cursor cursor)
{
    PersonDetails personDetails = PersonDetails.from(cursor);
    AddLog addLog = new AddLog();
    viewHolder.mName.setText(personDetails.getName());
    viewHolder.cursor = cursor;
    NumberFormat currency = addLog.changeamount();
    viewHolder.mAmount.setText(currency.format(personDetails.getAmount()));
}

and don't call

cursor.moveToPosition(position);

in you OnClick method.

And I prefer to implement your OnClickListner method in onBindViewHolder method not in viewHolder class.

Upvotes: 1

Related Questions