Android Recyclerview Onclicklistener 不适用于 Cursor

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

我正在开发一个包含 RecyclerviewCursorloader 的项目,当用户点击 recyclerview 中的项目时,它应该从中获取数据item 并开始新的 Activity。但是它给了我一个异常(exception) 尝试在空对象引用上调用接口(interface)方法“boolean android.database.Cursor.moveToPosition(int)”

我的适配器:

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 并在 Items 位置获取光标,我将不胜感激。

谢谢

最佳答案

您没有将光标设置到您的 viewHolder 上,只是在 onBindViewHolder 方法中设置

@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 方法中而不是在 viewHolder 类中实现您的 OnClickListner 方法。

关于Android Recyclerview Onclicklistener 不适用于 Cursor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37509486/

相关文章:

android - Android Studio 重构和基本搜索/替换之间有什么区别?

android - 在android中设置没有DateTime和TimePicker的闹钟

android - 如何增加 Android 微调器的可点击宽度?

java - onReceive 未在 Android 主屏幕小部件中为挂起的Intent 调用

java - 如果已经在 Android 中选中,如何防止第二次单击单选按钮?

Android Spannable 无法在回收器 View 适配器中工作

java - 使用 ItemTouchHelper.SimpleCallback 平滑滑动

Android - 滚动后无法点击 RecyclerView 内的项目

android - PreferenceFragment OnPreferenceClickListener() 只工作一次

java - 如何在每个 recyclerview 项目之间添加延迟?