【问题标题】: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();
    }

}

【问题讨论】:

    标签: java android android-recyclerview picasso android-context


    【解决方案1】:

    你有几个选择:

    1. 将 Context 作为参数传递给 FeedAdapter 并将其保留为类字段
    2. 在需要时使用依赖注入注入Context。我强烈建议阅读它。有一个很棒的工具——Square 的Dagger
    3. 从任何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();
    }
    

    解释为什么其他答案不是很好:

    1. 完全没有必要将Context 传递给适配器,因为RecyclerView 您可以从类内部访问它
    2. 在ViewHolder 级别获得Context 意味着您每次绑定或创建ViewHolder 时都会这样做。您重复操作。
    3. 我认为您无需担心任何内存泄漏。如果您的适配器在您的 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
                    

                    镇静丸:)

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2016-12-31
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-11-29
                      • 2017-04-28
                      • 1970-01-01
                      相关资源
                      最近更新 更多