将数据从 RecyclerView.Adapter 传递到片段 onClick
Posted
技术标签:
【中文标题】将数据从 RecyclerView.Adapter 传递到片段 onClick【英文标题】:Passing data from RecyclerView.Adapter to fragment onClick 【发布时间】:2019-08-19 16:18:19 【问题描述】:我试图弄清楚如何将数据从 RecyclerView 中的单击项目获取到片段中的列表视图。我似乎无法弄清楚如何做到这一点,因为我无法让我的捆绑包工作。
我尝试过 *** 上提供的各种解决方案,但都没有奏效。我已经设法从 recyclerview 获取信息,但我一直在试图弄清楚如何将它传递给片段。有人可以帮帮我吗?
适配器类:
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ViewHolder>
private Context context;
ArrayList<FoodActivity> list;
public FoodAdapter(ArrayList<FoodActivity> list)
this.list = list;
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item_food, parent, false);
return new ViewHolder(view);
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position)
holder.foods.setText(list.get(position).getName());
holder.carbo.setText(list.get(position).getCarbohydrates());
holder.protein.setText(list.get(position).getProtein());
holder.fats.setText(list.get(position).getFats());
//Get items from recyclerview when user clicks them. Then send them to FoodFragment
holder.itemView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
String foods = list.get(position).getName();
String carbo = list.get(position).getCarbohydrates();
String protein = list.get(position).getProtein();
String fats = list.get(position).getFats();
Toast.makeText(v.getContext(), "test: " + foods, Toast.LENGTH_SHORT).show();
);
@Override
public int getItemCount()
return list.size();
class ViewHolder extends RecyclerView.ViewHolder
TextView foods, carbo, fats, protein;
public ViewHolder(View itemView)
super(itemView);
carbo = itemView.findViewById(R.id.carbo);
protein = itemView.findViewById(R.id.protein);
fats = itemView.findViewById(R.id.fats);
foods = itemView.findViewById(R.id.food);
数据来自的Fragment:
public class TrackingFragment extends Fragment
DatabaseReference databaseReference;
ArrayList<FoodActivity> list;
RecyclerView recyclerView;
SearchView searchView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View view = inflater.inflate(R.layout.fragment_tracking, container, false);
databaseReference = FirebaseDatabase.getInstance().getReference().child("foods");
recyclerView = view.findViewById(R.id.rv);
searchView = view.findViewById(R.id.searchFood);
return view;
@Override
public void onStart()
super.onStart();
if(databaseReference != null)
databaseReference.addValueEventListener(new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
if(dataSnapshot.exists())
list = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren())
list.add(ds.getValue(FoodActivity.class));
FoodAdapter adapter = new FoodAdapter(list);
recyclerView.setAdapter(adapter);
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
Toast.makeText(getActivity(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
);
if(searchView != null)
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
@Override
public boolean onQueryTextSubmit(String query)
return false;
@Override
public boolean onQueryTextChange(String newText)
search(newText);
return true;
);
private void search(String str)
ArrayList<FoodActivity> searchList = new ArrayList<>();
for(FoodActivity object : list)
if(object.getName().toLowerCase().contains(str.toLowerCase()))
searchList.add(object);
FoodAdapter foodAdapter = new FoodAdapter(searchList);
recyclerView.setAdapter(foodAdapter);
以及它需要去的类:
public class FoodFragment extends Fragment
ImageButton addFood;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View view = inflater.inflate(R.layout.fragment_food, container, false);
addFood = view.findViewById(R.id.addFood);
addFood.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
FragmentTransaction fr = getFragmentManager().beginTransaction();
fr.replace(R.id.fragment_container, new TrackingFragment());
fr.addToBackStack(null).commit();
);
return view;
【问题讨论】:
根据这段代码很难说你在哪里使用FoodFragment
。两个片段是否在同一个活动中?你有TrackingFragment
和FoodAdapter
,对吗?
我不完全确定你的意思。从带有bottomNavigationView 的MenuActivity 调用FoodFragment,然后从FoodFragment 调用TrackingFragment。 FoodAdapter 已连接到 TrackingFrackment 是的。
但是你的布局到底是怎么设计的?你有一个 MenuActivity,它显示 FoodFragment,当你选择一些东西时,你用 TrackingFragment 替换你的食物 Fragment,还是你打开一个新的 Activity,它显示 Tracking Fragment?
在 MenuActivity 中,我在 FrameLayout 中有一个 fragment_container。每当我必须显示新片段时,我只需替换该容器中的片段。
【参考方案1】:
最简单的就是在activity中添加你需要的变量,用onClick()设置它们的值,然后在其他fragment中检索数据:
活动中:
String foods;
public String getFoods()
return foods;
public void setFoods(String foods)
this.foods = foods;
在适配器中:
holder.itemView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
((YourActivity)getActivity()).setFoods("Any value");
);
在目标片段中:
String foods = ((YourActivity)getActivity()).getFoods();
【讨论】:
这与 Kotlin 兼容吗? 是的,为什么不呢?但是这种方式太简单了,我不适合认真的开发人员。我建议你在适配器中使用回调。【参考方案2】:如下向你的适配器添加一个接口
public class FoodAdapter extends RecyclerView.Adapter<FoodAdapter.ViewHolder>
interface OnClickListener
void onClick(FoodActivity clickedItem);
private OnClickListener mCallback;
private ArrayList<FoodActivity> list;
public FoodAdapter(ArrayList<FoodActivity> list)
this.list = list;
public void setOnClickListener(OnClickListener callback)
mCallback = callback;
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item_food, parent, false);
return new ViewHolder(view);
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position)
holder.foods.setText(list.get(position).getName());
holder.carbo.setText(list.get(position).getCarbohydrates());
holder.protein.setText(list.get(position).getProtein());
holder.fats.setText(list.get(position).getFats());
//Get items from recyclerview when user clicks them. Then send them to FoodFragment
holder.itemView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
if (mCallback != null)
mCallback.onClick(list.get(position));
);
@Override
public int getItemCount()
return list.size();
class ViewHolder extends RecyclerView.ViewHolder
TextView foods, carbo, fats, protein;
public ViewHolder(View itemView)
super(itemView);
carbo = itemView.findViewById(R.id.carbo);
protein = itemView.findViewById(R.id.protein);
fats = itemView.findViewById(R.id.fats);
foods = itemView.findViewById(R.id.food);
【讨论】:
感谢您抽出宝贵时间回答。我已经尝试在 FoodFragment 中获取数据,但似乎无法让它工作(我之前没有使用过接口,我尝试过的东西也没有奏效)。你介意告诉我如何检索这些数据吗?【参考方案3】:当涉及到整个堆栈时,android 有时会有点复杂:
01 RecyclerView 适配器
/** 01. Some Adapter */
public class SomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private WeakReference<Context> mContext;
/** Constructor */
public SomeAdapter(@NonNull Context context)
this.mContext = new WeakReference<>(context);
@NonNull
protected Context getContext()
return this.mContext.get();
/** Call to Activity from within the adapter. */
private void someMethod()
SomeActivity activity = (SomeActivity) getContext();
synchronized(activity) activity.showLoginDialog();
02 AppCompatActivity
/** 02. Some Activity */
public class SomeActivity extends AppCompatActivity
@Nullable
private BaseFragment currentFragment = null;
/** Constructor */
public SomeActivity()
public void setCurrentFragment(Fragment fragment)
this.currentFragment = fragment;
/** Call to the current Fragment. */
public void someMethod()
if (currentFragment != null)
currentFragment.someMethod();
03 片段
/** Some Fragment */
public class SomeFragment extends Fragment
/** Constructor */
public SomeFragment()
@Override
public void onAttach(@NonNull Context context)
super.onAttach(context);
((BaseActivity) context).setCurrentFragment(this);
@Override
public void onDetach()
super.onDetach();
((BaseActivity) getActivity()).setCurrentFragment(this);
【讨论】:
【参考方案4】:要将数据从 FoodAdapter 获取到 TrackingFragment,您可以将 TrackingFragment(或其实现的接口,理想情况下)作为参数添加到 FoodAdapter 构造函数,然后使用该实例将 ViewHolder 点击转发到 TrackingFragment 进行处理。
要将数据从 TrackingFragment 获取到 FoodFragment,请使用 setTargetFragment/onActivityResult 模式进行片段 片段通信。这个答案有一个例子:https://***.com/a/13733914/3238938
【讨论】:
以上是关于将数据从 RecyclerView.Adapter 传递到片段 onClick的主要内容,如果未能解决你的问题,请参考以下文章
我无法从另一个带有 recyclerview.adaper 的片段中打开带有 recyclerview.adapter 的片段
如何从 RecyclerView.Adapter<CardAdapter.ViewHolder> 打开片段