리사이클 러 뷰 어댑터에서 컨텍스트를 가져 오는 방법


129

imageView에 URL을로드 할 수 있도록 피카소 라이브러리를 사용하려고하는데 피카소 라이브러리를 context올바르게 사용할 수 없습니다 .

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

}

답변:


290

여기에 몇 가지 옵션이 있습니다.

  1. 패스 ContextFeedAdapter에 인수로 및 클래스 필드로 유지
  2. Context필요할 때 주입하려면 종속성 주입을 사용하십시오 . 나는 그것에 대해 읽을 것을 강력히 제안합니다. 이를위한 훌륭한 도구가 있습니다 -Dagger by Square
  3. 모든 View개체 에서 가져옵니다 . 귀하의 경우 이것은 귀하에게 효과적 일 수 있습니다.

    holder.pub_image.getContext()

    으로는 pub_image입니다 ImageView.


64
뷰에서 컨텍스트를 가져 오는 세 번째 옵션을 선호합니다. 가장 간단하고 직접적인 솔루션입니다.
Dick Lucas

또는 클래스 인스턴스에 Picasso 인스턴스를 유지하고 지연로드하는 대신 Picasso 인스턴스를 전달하는 것이 훨씬 좋습니다.
Eric Cochran 2016

8
각 ViewHolder에는 생성자에서 전달하는 itemView의 인스턴스가 포함됩니다. itemView.getContext () :이 같은 하나 사용
안드레이 Lupsa

1
당신은 # 2를 할 수 없습니다. 나는 그것을 시도했지만 이것은 결국 ApplicationContext활동에 묶이지 않고 Glide 내에서 런타임 충돌로 이어질 것입니다.
boltup_im_coding

# 2를 사용하려는 경우 구성 요소 개체를 어댑터에 전달하는 방법은 무엇입니까?
Ezio

32

전역 변수를 추가 할 수 있습니다.

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

해피 코딩 :)


나를 위해 일 했어! 감사합니다
케니 Dabiri

21
나는 컨텍스트에 대한 글로벌 참조를 갖는 것을 강력히 제안합니다. 이것은 끔찍한 메모리 누수 문제로 이어질 수 있습니다 !!
solidak

1
뷰 홀더를 하위 클래스로 만들면 비공개가 될 수 있습니다.
r3dm4n

어댑터가 RecyclerView에 연결되어 있으면 어쨌든 해당 컨텍스트가 필요합니다. 어댑터를 연결 해제 할 수 있다면 어떤 이유로 든이 어댑터가 분리 된 후이 어댑터에 대한 강력한 참조를 유지하지 않는 한 괜찮습니다.이 경우 캐시 된 컨텍스트를 지워야합니다 onDetachedFromRecyclerView. 이와 같은 방법이 있습니다.
androidguy

19

짧은 답변:

Context context;

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

다른 답변이 좋지 않은 이유 설명 :

  1. Context어댑터에 전달 하는 RecyclerView것은 클래스 내부에서 액세스 할 수 있으므로 완전히 불필요 합니다.
  2. 레벨 Context에서 획득 ViewHolder한다는 것은 ViewHolder. 작업을 복제합니다.
  3. 메모리 누수에 대해 걱정할 필요가 없다고 생각합니다. 어댑터가 Activity수명을 벗어나면 (이상 할 수 있음) 이미 누출이있는 것입니다.

이 경우 onDetachedFromRecyclerView()컨텍스트를 구현 하고 해제 해야 합니까?
John Pang

@JohnPang은 당신이 극도로 방어 적이기를 원하지 않는 한 정말 아닙니다. 활동 내에서 어댑터 참조를 유지하면 안전합니다.
Maciej Beimcik

17

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

다음을 정의 할 수 있습니다.

Context ctx; 

그리고 onCreate초기화 ctx할 때 :

ctx=parent.getContext(); 

참고 : 상위는 ViewGroup입니다.


5

먼저 전 세계적으로 선언

Context mContext;

생성자와 컨텍스트를 수정하여 전달합니다.

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

그런 다음 mContext필요한 곳에서 사용하십시오.


5

view.getContext () 처럼 사용할 수 있습니다.

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

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


        }
    });


4

FeedAdapter의 생성자를 만듭니다.

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

그리고 활동 중

FeedAdapter obj = new FeedAdapter(this);

2

먼저 전역 변수를 추가하십시오.

Context mContext;

그런 다음 생성자를 다음으로 변경하십시오.

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

어댑터를 만들 때 컨텍스트를 전달합니다.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);

1
View mView;
mView.getContext();

이 코드가 문제를 해결할 수 있지만, 이것이 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이 될 것이며 아마도 더 많은 찬성표를 얻게 될 것입니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 제발 편집 설명을 추가하고 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을. 리뷰에서
더블 비프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.