Android Recyclerview Onclicklistener无法使用Cursor

时间:2016-05-29 11:41:52

标签: android onclicklistener android-recyclerview android-cursor android-cursorloader

我正在开展一个包含RecyclerviewCursorloader的项目,当用户点击recyclerview中的项目时,它应该从项目中获取数据并开始新的Activity但相反,它给了我一个例外 Attempt to invoke interface method 'boolean android.database.Cursor.moveToPosition(int)' on a null object reference

我的适配器:

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();
        }
    }
}

光标适配器:

    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
            }
        }

}

我真的很感激,如果你们中的任何一个人知道一个比这更好的解决方案来启动onclicklistenter并在项目位置获得光标。

谢谢

1 个答案:

答案 0 :(得分:1)

您没有将光标设置为只在onBindViewHolder方法中设置的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());
    viewHolder.cursor = cursor;
    NumberFormat currency = addLog.changeamount();
    viewHolder.mAmount.setText(currency.format(personDetails.getAmount()));
}

并且不要打电话

cursor.moveToPosition(position);

在OnClick方法中。

我更喜欢在onBindViewHolder方法中实现OnClickListner方法而不是在viewHolder类中。