如何在回收器视图适配器中获取上下文
Posted
技术标签:
【中文标题】如何在回收器视图适配器中获取上下文【英文标题】:How to get a context in a recycler view adapter 【发布时间】:2015-11-15 04:49:30 【问题描述】:我正在尝试使用 picasso 库来将 url 加载到 imageView,但我无法让 context
正确使用 picasso 库。
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.ViewHolder>
private List<Post> mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder
// each data item is just a string in this case
public TextView txtHeader;
public ImageView pub_image;
public ViewHolder(View v)
super(v);
txtHeader = (TextView) v.findViewById(R.id.firstline);
pub_image = (ImageView) v.findViewById(R.id.imageView);
// Provide a suitable constructor (depends on the kind of dataset)
public FeedAdapter(List<Post> myDataset)
mDataset = myDataset;
// Create new views (invoked by the layout manager)
@Override
public FeedAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType)
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.feedholder, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position)
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.txtHeader.setText(mDataset.get(position).getPost_text());
Picasso.with(this.context).load("http://i.imgur.com/DvpvklR.png").into(holder.pub_image);
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount()
return mDataset.size();
【问题讨论】:
【参考方案1】:你有几个选择:
-
将
Context
作为参数传递给 FeedAdapter 并将其保留为类字段
在需要时使用依赖注入注入Context
。我强烈建议阅读它。有一个很棒的工具——Square 的Dagger
从任何View
对象中获取它。在您的情况下,这可能对您有用:
holder.pub_image.getContext()
因为pub_image
是ImageView
。
【讨论】:
我更喜欢第三个选项,从视图中获取上下文。这是最简单、最直接的解决方案。 或者,更好的是,传入 Picasso 实例,而不是在类实例上保存 Picasso 实例并延迟加载它。 每个 ViewHolder 都包含您在构造函数中传递的 itemView 实例。像这样使用那个: itemView.getContext() 你不能做#2,对吗?我试过了,但这最终会成为你的ApplicationContext
并且与活动无关,从而导致 Glide 内部运行时崩溃。
如果我想使用#2,如何将组件对象传递给适配器?【参考方案2】:
编辑 正如solidak在the comments section中所说,原来的答案可能会导致内存泄漏问题,使用这种方法是不好的做法,所以最好使用另一种方法来访问上下文。
原答案:
你可以添加一个全局变量:
private Context context;
然后从这里分配上下文:
@Override
public FeedAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
// create a new view
View v=LayoutInflater.from(parent.getContext()).inflate(R.layout.feedholder, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
// set the Context here
context = parent.getContext();
return vh;
编码愉快:)
【讨论】:
也为我工作!谢谢 我强烈建议反对对 Context 进行全局引用。这可能会导致可怕的内存泄漏问题! 如果你是viewholder的子类,它可以是私有的。 如果适配器附加到 RecyclerView 则保证无论如何都需要该上下文。如果您可以取消附加适配器,那么它仍然可以,除非由于某种原因您在分离后持有对该适配器的强引用,在这种情况下您应该清除缓存的上下文,有一个像onDetachedFromRecyclerView
这样的方法。 【参考方案3】:
简答:
Context context;
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView)
super.onAttachedToRecyclerView(recyclerView);
context = recyclerView.getContext();
解释为什么其他答案不是很好:
-
完全没有必要将
Context
传递给适配器,因为RecyclerView
您可以从类内部访问它
在ViewHolder
级别获得Context
意味着您每次绑定或创建ViewHolder
时都会这样做。您重复操作。
我认为您无需担心任何内存泄漏。如果您的适配器在您的 Activity
使用寿命之外徘徊(这很奇怪),那么您已经有泄漏。
【讨论】:
在这种情况下,我们是否应该实现onDetachedFromRecyclerView()
并释放上下文?
@JohnPang 不是真的,除非你想非常防御。如果您将适配器引用保留在 Activity 中,那么您是安全的。
如果您不在活动中保留对适配器的引用? :P
你自己一个人 :) 今天我想我会按照@JohnPang 的建议实现这个方法,以防万一【参考方案4】:
您可以使用 pub_image 上下文 (holder.pub_image.getContext()
) :
@Override
public void onBindViewHolder(ViewHolder ViewHolder, int position)
holder.txtHeader.setText(mDataset.get(position).getPost_text());
Picasso.with(holder.pub_image.getContext()).load("http://i.imgur.com/DvpvklR.png").into(holder.pub_image);
【讨论】:
【参考方案5】:你可以用这个:
itemView.getContext()
【讨论】:
【参考方案6】:你可以像这样使用view.getContext()
示例
holder.tv_room_name.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Toast.makeText(v.getContext(), "", Toast.LENGTH_SHORT).show();
);
【讨论】:
【参考方案7】:你可以定义:
Context ctx;
在onCreate
上初始化ctx
为:
ctx=parent.getContext();
注意:Parent 是一个 ViewGroup。
【讨论】:
【参考方案8】:创建 FeedAdapter 的构造函数:
Context context; //global
public FeedAdapter(Context context)
this.context = context;
在活动中
FeedAdapter obj = new FeedAdapter(this);
【讨论】:
【参考方案9】:首先全局声明
Context mContext;
通过构造函数传递上下文,通过修改它。
public FeedAdapter(List<Post> myDataset, Context context)
mDataset = myDataset;
this.mContext = context;
然后在任何需要的地方使用mContext
【讨论】:
【参考方案10】:View mView;
mView.getContext();
【讨论】:
虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案添加解释并说明适用的限制和假设。 From Review【参考方案11】:先添加一个全局变量
Context mContext;
然后把你的构造函数改成这个
public FeedAdapter(Context context, List<Post> myDataset)
mContext = context;
mDataset = myDataset;
在创建适配器时传递你的上下文。
FeedAdapter myAdapter = new FeedAdapter(this,myDataset);
【讨论】:
【参考方案12】:如果您在布局上使用数据绑定,您可以从holder
获得context
。下面是一个例子。
@Override
public void onBindViewHolder(@NonNull GenericViewHolder holder, int position)
View currentView = holder.binding.getRoot().findViewById(R.id.cycle_count_manage_location_line_layout);// id of your root layout
currentView.setBackgroundColor(ContextCompat.getColor(holder.binding.getRoot().getContext(), R.color.light_green));
【讨论】:
【参考方案13】:解决方案:
当使用视图绑定时使用
holder.binding.productImg.context
否则使用
holder.productImg.context
镇静丸:)
【讨论】:
以上是关于如何在回收器视图适配器中获取上下文的主要内容,如果未能解决你的问题,请参考以下文章
如何在 TabLayout 中找到由 RecyclerView 打开的对话框的上下文?