【问题标题】:Doubts about RecyclerView with CursorAdapter对 RecyclerView 与 CursorAdapter 的质疑
【发布时间】:2016-11-28 03:39:39
【问题描述】:

我阅读了 this thread 关于 RecyclerViews 和 Cursor 适配器的内容,我正在尝试使用第一个 solution。我对 OnViewHolder 函数的实现感到困惑。我知道 OnViewHolder 可以由 (ViewHolder, int) 或 (ViewHolder, Cursor) 调用,但我不知道如何在我的项目中使用它。

这是我原来的适配器

public class FeedAdapter extends CursorAdapter {

/*
Etiqueta de Depuración
 */
private static final String TAG = FeedAdapter.class.getSimpleName();

/**
 * View holder para evitar multiples llamadas de findViewById()
 */
static class ViewHolder {
    TextView titulo;
    TextView descripcion;

    int tituloI;
    int descripcionI;
}

public FeedAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);

}

public View newView(Context context, Cursor cursor, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());

    View view = inflater.inflate(R.layout.item_layout, null, false);

    ViewHolder vh = new ViewHolder();

    // Almacenar referencias
    vh.titulo = (TextView) view.findViewById(R.id.titulo);
    vh.descripcion = (TextView) view.findViewById(R.id.descripcion);

    // Setear indices
    vh.tituloI = cursor.getColumnIndex(ScriptDatabase.ColumnEntradas.TITULO);
    vh.descripcionI = cursor.getColumnIndex(ScriptDatabase.ColumnEntradas.DESCRIPCION);

    view.setTag(vh);

    return view;
}

public void bindView(View view, Context context, Cursor cursor) {

    final ViewHolder vh = (ViewHolder) view.getTag();

    // Setear el texto al titulo
    vh.titulo.setText(cursor.getString(vh.tituloI));

    // Obtener acceso a la descripción y su longitud
    vh.descripcion.setText(descripcion);

}
}

我的带有 RecyclerView 的新适配器。 OnBindViewHolder 未完成,因为我不知道如何设置。

public class RVAdapter extends CursorRecyclerViewAdapter<RVAdapter.ViewHolder>{
private Cursor mCursorAdapter;

public RVAdapter(Context context, Cursor cursor){
    super(context,cursor);
}

public static class ViewHolder extends RecyclerView.ViewHolder {
    CardView cv;
    TextView titulo;
    TextView descripcion;

    int tituloI;
    int descripcionI;

    public ViewHolder (View view){
        super(view);
        cv = (CardView) itemView.findViewById(R.id.cv);
        titulo = (TextView) itemView.findViewById(R.id.titulo);
        descripcion = (TextView) itemView.findViewById(R.id.descripcion);
    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_layout, parent, false);
    ViewHolder vh = new ViewHolder(itemView);
    return vh;
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    mCursorAdapter.moveToPosition(position);

    final ViewHolder vh = (ViewHolder) view.getTag();

}
}

在这种情况下我应该使用“onBindViewHolder(ViewHolder viewHolder, Cursor cursor)”吗?我怎样才能让它工作?

编辑 1

这是扩展我的 RVAdapter 的抽象类

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

}

【问题讨论】:

    标签: android listview android-recyclerview android-cursoradapter


    【解决方案1】:

    您可以使用 ViewHolder 和 position 来访问您的视图和字段,例如 下面:

     @Override
        public void onBindViewHolder(ViewHolder viewHolder, final int position) {
            StructName name = names.get(position);
            viewHolder.txttitle.setText(name.title);
            viewHolder.rootItem.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                }
            });
    
        }
    

    比使用游标更容易 如果这有帮助,请告诉我。

    【讨论】:

    • 抱歉耽搁了。我意识到 CursorRecyclerViewAdapter 需要使用 Cursors 实现 onBindViewHolder,但我不知道如何使用 Cursor 变量移动位置。任何想法 ?非常感谢您的有趣回答
    • 我用抽象函数 CursorRecyclerView 编辑了我的原始帖子
    【解决方案2】:

    使用光标,因为它更节省内存。

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int position) {
        mCursorAdapter.moveToPosition(position);
        viewHolder.titulo.setText(mCursorAdapter.getString(mCursorAdapter.getColumnIndex(ScriptDatabase.ColumnEntradas.TITULO)));
        viewHolder.descripcion.setText(mCursorAdapter.getString(mCursorAdapter.getColumnIndex(ScriptDatabase.ColumnEntradas.DESCRIPCION)));
    }
    

    【讨论】:

    • 如果我使用游标,位置不能是 int 但游标类型和 moveToPostion 必须与 int 变量一起使用。如何使用光标类型移动位置? public void onBindViewHolder(ViewHolder viewHolder, Cursor cursor)
    • 我的意思是在你的类中使用游标类成员(你已经做过的事情,mCursorAdapter 成员),而不是像 HPbyP 建议的那样使用对象数组/列表。 "names.get(position);"他写道,暗示您有一个列表类成员。不要寻求这样的解决方案,而是使用您的 mCursorAdapter。至于 RVAdapter.onBindViewHolder 方法,它的签名必须是 public void onBindViewHolder(ViewHolder, int)。
    猜你喜欢
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2020-08-01
    • 2015-01-01
    • 1970-01-01
    • 2014-02-03
    • 2023-03-29
    相关资源
    最近更新 更多