如何从 RecyclerView 适配器返回数据? [英] How can I return data from a RecyclerView adapter?

查看:50
本文介绍了如何从 RecyclerView 适配器返回数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 RecyclerView,其中在 RecyclerView 的每个对象中都有一个复选框.每次按下其中一个复选框时,我都想在适配器上插入数据.有一次我完成了(按下 Fragment 上的一个按钮,将 Adapter 设置为 RecyclerView)必须返回数据.

我的RecyclerViewAdapter的代码(简化版)是:

public List数据;公共类 MyCustomAdapter 扩展 RecyclerView.Adapter{公共 MyCustomAdapter(列表 数据){this.data=数据;}public MyCustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {查看视图= LayoutInflater.from(parent.getContext()).inflate(R.layout_car_item, parent, false);返回新的 MyCustomViewHolder(view);}公共无效 onBindViewHolder(最终 MyCustomViewHolder 持有人,最终 int 位置){holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@覆盖public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {//这里添加我要存储的数据持有人.getItem();}});}公共类 MyCustomViewHolder 扩展 RecyclerView.ViewHolder{公共 MyCustomViewHolder(查看 itemView){超级(项目视图);//这里我参考了Adapter布局的所有元素}公共无效getItem(){Log.d("证明", "" + data.size());}}}

我已经创建了 getItem() 方法来获取 MyCustomViewHolder 中的数据,但我不知道如何将数据返回到 Fragment其中我将 Adapter 设置为 RecyclerView.

有什么方法可以将数据从RecyclerViewAdapter返回到我设置的Fragment?

提前致谢!

解决方案

更新回复:

使用 CarItems 列表的替代方法:

@OnClick(...)公共无效 onButtonClicked() {int size = ((MyCustomAdapter) mRecyclerView.getAdapter()).getItemCount();for (int i = 0; i < size; i++) {if (((MyCustomAdapter) mRecyclerView.getAdapter()).isItemChecked(i)) {//获取每个选中的项目CarItem carItem = (MyCustomAdapter) mRecyclerView.getAdapter()).getItem(i);//对项目执行一些操作,例如将其保存到选定的项目数组中.}}}

您还可以向适配器添加一个 getCheckedItems() 方法:

public ListgetCheckedItems() {列表checkItems = new ArrayList<>();for (int i = 0; i < getItemCount(); i++) {如果(isItemChecked(i)){checkItems.add(getItem(i));}}返回checkedItems;}

并从 RecyclerView 像这样使用它:

((MyCustomAdapter) mRecyclerView.getAdapter()).getCheckedItems();

<小时><块引用>

有没有办法从RecyclerView的Adapter返回数据到我设置它的 Fragment?

通常用于操作片段中的数据:

将下面的方法添加到适配器,并通过 recyclerView 从片段中调用它们,将其投射到您的自定义适配器:((MyCustomAdapter) mRecyclerView.getAdapter()).getItem(...);

public void setListItems(List data) {this.data = 数据;}公共列表 getListItems() {返回数据;}@覆盖公共 int getItemCount() {返回 this.data.size();}公共 CarItem getItem(int position) {返回 data.get(position);}public void setItem(CarItem item, int position) {数据集(位置,项目);}

<小时><块引用>

我有一个 RecyclerView,其中在 RecyclerView 的每个对象中我有一个复选框.每次按下其中一个复选框时,我都会喜欢在 Adapter 上插入数据.

管理多选状态和保存状态

阅读

<小时><块引用>

我已经创建了 getItem() 方法来获取里面的数据MyCustomViewHolder 但我不知道如何将数据返回给我将 Adapter 设置为 RecyclerView 的片段.

从视图持有者设置/获取数据

这些方法也可用于获取数据,可能使用 setTag()/getTag() 机制.

viewHolder.itemView.setTag(yourNewData);/*** 返回此视图的标签.** @return 存储在此视图中的对象作为标签,否则 {@code null}*         放** @see #setTag(Object)* @see #getTag(int)*/@ViewDebug.ExportedProperty公共对象 getTag() {返回 mTag;}/*** 设置与此视图关联的标签.标签可用于标记* 在其层次结构中的视图,并且在视图中不必是唯一的* 等级制度.标签也可用于在视图中存储数据,而无需* 求助于另一种数据结构.** @param 标记一个对象来标记视图** @see #getTag()* @see #setTag(int, Object)*/public void setTag(最终对象标签){mTag = 标签;}

<块引用>

有一次我完成了(按将适配器设置为 RecyclerView 的 Fragment 上的按钮)必须返回数据.

我需要额外的信息,了解当数据返回时您要做什么,以及您再次将适配器设置为 recyclerview 的原因.

findViewHolderForAdapterPosition(int)

/*** 返回数据集给定位置中项目的 ViewHolder.不像* {@link #findViewHolderForLayoutPosition(int)} 此方法考虑任何待处理* 可能尚未反映到布局中的适配器更改.另一方面,如果* {@link Adapter#notifyDataSetChanged()} 已被调用但新布局尚未被调用* 尚未计算,此方法将返回 null;由于新的观点* 在计算布局之前是未知的.* <p>* 此方法仅检查 RecyclerView 的子项.如果在给定的项目* <代码>位置没有布局,它<em>不会</em>创建一个新的.** @param position 项目在适配器数据集中的位置* @return 位置处的ViewHolder或者 null 如果没有这样的项目*/公共 ViewHolder findViewHolderForAdapterPosition(int position) {如果(mDataSetHasChangedAfterLayout){返回空;}final int childCount = mChildHelper.getUnfilteredChildCount();for (int i = 0; i < childCount; i++) {最终的 ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));if (holder != null && !holder.isRemoved() && getAdapterPositionFor(holder) == position) {退货持有人;}}返回空;}@OnClick(...)公共无效 onButtonClicked() {int size = ((MyCustomAdapter) mRecyclerView.getAdapter()).getItemCount();for (int i = 0; i < size; i++) {ViewHolder vh = (MyCustomViewHolder) findViewHolderForAdapterPosition(i);if (vh != null && ((MyCustomAdapter) mRecyclerView.getAdapter()).isItemChecked(i)) {Object obj = vh.itemView.getTag();//操作这个视图持有者中包含的数据//但也许将数据保存在 CarItem 中会更好//并且不要从适配器外部操作 VH}}}

I have a RecyclerView in which in each object of the RecyclerView I have a checkbox. Each time one of the checkboxes is pressed I would like to insert data on the Adapter. One time I finished (press a button on the Fragment that sets the Adapter to the RecyclerView) the data have to be returned.

My code(simplified) of the Adapter of the RecyclerView is:

public List<CarItem> data; 
public class MyCustomAdapter extends RecyclerView.Adapter<MyCustomAdapter.MyCustomViewHolder>  {

    public MyCustomAdapter(List<CarItem> data) {
        this.data=data;
    }

    public MyCustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout_car_item, parent, false);
        return new MyCustomViewHolder(view);
    }

    public void onBindViewHolder(final MyCustomViewHolder holder, final int position) {
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                  @Override
                  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                       //Here I add the data that I want to store
                       holder.getItem();
                  }
            });
    }

    public class MyCustomViewHolder extends RecyclerView.ViewHolder{
          public MyCustomViewHolder (View itemView) {
              super(itemView);
              //Here I make reference to all the elements of the layout of the Adapter
          }

          public void getItem(){
              Log.d("prove", "" + data.size());
          }
    }
}

I have created getItem() method to get the data inside MyCustomViewHolder but I do not know how to return the data to the Fragment in which I sets the Adapter to the RecyclerView.

Is there some way to return data from the Adapter of the RecyclerView to the Fragment in which I set it?

Thanks in advance!

解决方案

Updated response:

Alternative using the CarItems list:

@OnClick(...)
public void onButtonClicked() {
    int size = ((MyCustomAdapter) mRecyclerView.getAdapter()).getItemCount();
    for (int i = 0; i < size; i++) {
        if (((MyCustomAdapter) mRecyclerView.getAdapter()).isItemChecked(i)) {
            // Get each selected item
            CarItem carItem = (MyCustomAdapter) mRecyclerView.getAdapter()).getItem(i);
            // Do something with the item like save it to a selected items array.
        }
    }
}

You also can add a getCheckedItems() method to the adapter:

public List<CarItem> getCheckedItems() {
    List<CarItem> checkedItems = new ArrayList<>();
    for (int i = 0; i < getItemCount(); i++) {
        if (isItemChecked(i)) {
            checkedItems.add(getItem(i));
        }
    }
    return checkedItems;
}

and use it from the RecyclerView like this:

((MyCustomAdapter) mRecyclerView.getAdapter()).getCheckedItems();


Is there some way to return data from the Adapter of the RecyclerView to the Fragment in which I set it?

In general to manipulate the data from your fragment:

Add the methods below to the adapter and call them from the fragment via the recyclerView casting it to your custom adapter: ((MyCustomAdapter) mRecyclerView.getAdapter()).getItem(...);

public void setListItems(List<CarItem> data) {
    this.data = data;
}

public List getListItems() {
    return data;
}

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

public CarItem getItem(int position) {
    return data.get(position);
}

public void setItem(CarItem item, int position) {
    data.set(position, item);
}


I have a RecyclerView in which in each object of the RecyclerView I have a checkbox. Each time one of the checkboxes is pressed I would like to insert data on the Adapter.

Manage multichoice state and saved state

Read this explanation and check this sample app for multichoice.

This library also extends adapter for selection using SparseBooleanArray to save selected items.

Or use this to save the checked state and use it later when button is pressed to only access to the data of the checked items:

public class MyCustomAdapter extends RecyclerView.Adapter<MyCustomAdapter.MyCustomViewHolder>  {
    private ArrayList<CarItem> data;
    private SparseBooleanArray checkedState = new SparseBooleanArray();

    public void setCheckedState(int position, boolean checked) {
        checkedState.append(position, checked);
    }

    public boolean isItemChecked(int position) {
        return checkedState.get(position);
    }

    public SparseBooleanArray getCheckedState() {
        return checkedState;
    }

    public void onBindViewHolder(final MyCustomViewHolder holder, final int position) {
        holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                  @Override
                  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                       setCheckedState(holder.getAdapterPosition(), isChecked);
                       //Here I add the data that I want to store
                       if (isChecked) {
                           data.set(holder.getAdapterPosition(), holder.getItem());
                       } else {
                           data.set(holder.getAdapterPosition(), null);
                       }

              }
        });
}

Reason to use adapter position on this related Google I/O 2016 video:


I have created getItem() method to get the data inside MyCustomViewHolder but I do not know how to return the data to the Fragment in which I sets the Adapter to the RecyclerView.

Set/get data to/from the view holder

Also these methods can be useful to get the data, perhaps using the setTag()/getTag() mechanism.

viewHolder.itemView.setTag(yourNewData);

/**
 * Returns this view's tag.
 *
 * @return the Object stored in this view as a tag, or {@code null} if not
 *         set
 *
 * @see #setTag(Object)
 * @see #getTag(int)
 */
@ViewDebug.ExportedProperty
public Object getTag() {
    return mTag;
}

/**
 * Sets the tag associated with this view. A tag can be used to mark
 * a view in its hierarchy and does not have to be unique within the
 * hierarchy. Tags can also be used to store data within a view without
 * resorting to another data structure.
 *
 * @param tag an Object to tag the view with
 *
 * @see #getTag()
 * @see #setTag(int, Object)
 */
public void setTag(final Object tag) {
    mTag = tag;
}

One time I finished (press a button on the Fragment that sets the Adapter to the RecyclerView) the data have to be returned.

I would need extra info about what are you trying to do when the data is returned and the reason you set the adapter to the recyclerview another time here.

findViewHolderForAdapterPosition(int)

/**
 * Return the ViewHolder for the item in the given position of the data set. Unlike
 * {@link #findViewHolderForLayoutPosition(int)} this method takes into account any pending
 * adapter changes that may not be reflected to the layout yet. On the other hand, if
 * {@link Adapter#notifyDataSetChanged()} has been called but the new layout has not been
 * calculated yet, this method will return <code>null</code> since the new positions of views
 * are unknown until the layout is calculated.
 * <p>
 * This method checks only the children of RecyclerView. If the item at the given
 * <code>position</code> is not laid out, it <em>will not</em> create a new one.
 *
 * @param position The position of the item in the data set of the adapter
 * @return The ViewHolder at <code>position</code> or null if there is no such item
 */
public ViewHolder findViewHolderForAdapterPosition(int position) {
    if (mDataSetHasChangedAfterLayout) {
        return null;
    }
    final int childCount = mChildHelper.getUnfilteredChildCount();
    for (int i = 0; i < childCount; i++) {
        final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i));
        if (holder != null && !holder.isRemoved() && getAdapterPositionFor(holder) == position) {
            return holder;
        }
    }
    return null;
}

@OnClick(...)
public void onButtonClicked() {
    int size = ((MyCustomAdapter) mRecyclerView.getAdapter()).getItemCount();
    for (int i = 0; i < size; i++) {
        ViewHolder vh = (MyCustomViewHolder) findViewHolderForAdapterPosition(i);
        if (vh != null && ((MyCustomAdapter) mRecyclerView.getAdapter()).isItemChecked(i)) {
            Object obj = vh.itemView.getTag();
            // Manipulate the data contained in this view holder
            // but perhaps would be better to save the data in the CarItem
            // and don't manipulate the VH from outside the adapter
        }
    }
}

这篇关于如何从 RecyclerView 适配器返回数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆