Làm thế nào để có được một bối cảnh trong một bộ chuyển đổi xem tái chế


129

Tôi đang cố gắng sử dụng thư viện picasso để có thể tải url vào imageView, nhưng tôi không thể contextsử dụng thư viện picasso một cách chính xác.

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();
    }

}

Câu trả lời:


290

Bạn có một vài lựa chọn ở đây:

  1. Vượt qua Contextnhư một tham số để FeedAdapter và giữ nó như trường lớp
  2. Sử dụng tiêm phụ thuộc để tiêm Contextkhi bạn cần nó. Tôi đề nghị đọc về nó. Có một công cụ tuyệt vời cho việc đó - Dagger by Square
  3. Lấy nó từ bất kỳ Viewđối tượng. Trong trường hợp của bạn, điều này có thể làm việc cho bạn:

    holder.pub_image.getContext()

    Như pub_imagelà một ImageView.


64
Tôi thích tùy chọn thứ ba, lấy bối cảnh từ chế độ xem. Đó là giải pháp đơn giản và đơn giản nhất.
Dick Lucas

hoặc, tốt hơn nhiều, vượt qua trong thể hiện Picasso, thay vì giữ một cá thể Picasso trên cá thể lớp và lười tải nó.
Eric Cochran

8
Mỗi ViewHolder chứa một thể hiện của itemView mà bạn truyền vào hàm tạo. Sử dụng cái đó như thế này: itemView.getContext ()
Andrei Lupsa

1
Bạn không thể làm # 2, bạn có thể? Tôi đã thử điều đó, nhưng điều này cuối cùng sẽ là của bạn ApplicationContextvà không bị ràng buộc với hoạt động, dẫn đến sự cố thời gian chạy từ bên trong Glide.
boltup_im_coding

Làm thế nào để chuyển đối tượng thành phần cho bộ điều hợp trong trường hợp tôi muốn sử dụng # 2?
Ezio

32

Bạn có thể thêm biến toàn cục:

private Context context;

sau đó gán bối cảnh từ đây:

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

Chúc mừng mã hóa :)


Làm việc cho tôi quá! Cảm ơn
Kenny Dabiri

21
Tôi thực sự khuyên bạn nên LẠI có các tài liệu tham khảo toàn cầu về Ngữ cảnh. Điều này có thể dẫn đến các vấn đề rò rỉ bộ nhớ khủng khiếp !!
solidak

1
nếu bạn xem lớp con, nó có thể là riêng tư.
r3dm4n

Nếu bộ điều hợp được gắn vào RecyclerView thì bối cảnh đó vẫn được đảm bảo là cần thiết. Nếu bạn có thể hủy kết nối bộ điều hợp, thì nó vẫn ổn trừ khi vì lý do nào đó bạn giữ tham chiếu mạnh đến bộ điều hợp này sau khi nó bị tách ra, trong trường hợp đó bạn nên xóa bối cảnh được lưu trong bộ nhớ cache, có một phương pháp như onDetachedFromRecyclerViewhoặc một cái gì đó.
androidguy

19

Câu trả lời ngắn:

Context context;

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
    context = recyclerView.getContext();
}

Giải thích tại sao các câu trả lời khác không tuyệt vời:

  1. Chuyển Contextđến bộ điều hợp là hoàn toàn không cần thiết, vì RecyclerViewbạn có thể truy cập nó từ bên trong lớp
  2. Có được ContextViewHoldercấp độ có nghĩa là bạn làm điều đó mỗi khi bạn liên kết hoặc tạo một ViewHolder. Bạn nhân đôi thao tác.
  3. Tôi không nghĩ rằng bạn cần phải lo lắng về bất kỳ rò rỉ bộ nhớ. Nếu bộ điều hợp của bạn nằm ngoài Activitytuổi thọ của bạn (điều này thật kỳ lạ) thì bạn đã bị rò rỉ.

Trong trường hợp này, chúng ta sẽ thực hiện onDetachedFromRecyclerView()và phát hành bối cảnh?
John Pang

@JohnPang không thực sự trừ khi bạn muốn cực kỳ phòng thủ. Nếu bạn giữ tham chiếu bộ điều hợp trong Hoạt động, bạn an toàn.
Maciej Beimcik

17

Bạn có thể sử dụng bối cảnh 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);


}

6

Bạn có thể định nghĩa:

Context ctx; 

onCreatekhởi tạo ctxđể:

ctx=parent.getContext(); 

Lưu ý: Phụ huynh là một Viewgroup.


5

Tuyên bố đầu tiên trên toàn cầu

Context mContext;

vượt qua bối cảnh với hàm tạo, bằng cách sửa đổi nó.

public FeedAdapter(List<Post> myDataset, Context context) {
    mDataset = myDataset;
    this.mContext = context;
}

sau đó sử dụng mContextbất cứ nơi nào bạn cần


5

Bạn có thể sử dụng như view.getContext ()

Thí dụ

holder.tv_room_name.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Toast.makeText(v.getContext(), "", Toast.LENGTH_SHORT).show();


        }
    });


4

Tạo một hàm tạo của FeedAd CHƯƠNG:

Context context; //global
public FeedAdapter(Context context)
{
   this.context = context;  
}

và trong hoạt động

FeedAdapter obj = new FeedAdapter(this);

2

Đầu tiên thêm một biến toàn cục

Context mContext;

Sau đó thay đổi hàm tạo của bạn thành cái này

public FeedAdapter(Context context, List<Post> myDataset) {
    mContext = context;
    mDataset = myDataset;
}

Việc vượt qua bối cảnh của bạn khi tạo bộ điều hợp.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);

1
View mView;
mView.getContext();

Mặc dù mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thức và lý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn và có thể dẫn đến nhiều lượt bình chọn hơn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ người hỏi bây giờ. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng. Từ đánh giá
tiếng bíp đôi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.