简体   繁体   中英

In RecyclerView.Adapter non static field cannot be referenced in onclick method

In my RecyclerView.Adapter I have a non static field but I have to Implement onClick in my ViewHolder but there is a problem that in onClick method an error occurred non static field cannot be referenced from a static context but I can't declare my field as static because that recycler view is created multiple times in tab fragments and values are overridden so please give me a proper solution.

Edit

here is my code

public class RecyclerAdapter extends RecyclerView.Adapter{

public static final int VIEW_ITEM = 1;
public static final int VIEW_PROG = 0;

public ArrayList<BlogPosts> blogPostsArrayList;
public OnLoadMoreListener onLoadMoreListener;

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public TextView title, category, time;
    public ImageView blogImage;
    public static Context context;

    public ViewHolder(View view) {
        super(view);
        context = view.getContext();
        title = (TextView) view.findViewById(R.id.textView);
        category = (TextView) view.findViewById(R.id.category);
        time = (TextView) view.findViewById(R.id.textTime);
        blogImage = (ImageView) view.findViewById(R.id.newsListImage);

        view.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        try {
            RecyclerAdapter blogsListRecyclerAdapter = new RecyclerAdapter();
            BlogPosts details;
            details = blogPostsArrayList.get(getPosition());// Problem is here
            Intent i = new Intent(context, ActivityNewsDetail.class);

            context.startActivity(i);
        } catch (Exception e) {

        }
    }


}

public static class ProgressViewHolder extends RecyclerView.ViewHolder {
    public ProgressBar progressBar;

    public ProgressViewHolder(View v) {
        super(v);
        progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
    }
}

public RecyclerAdapter(ArrayList<BlogPosts> blogPostsArrayList) {
    this.blogPostsArrayList = blogPostsArrayList;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    View v;
    if (viewType == VIEW_ITEM) {
        v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.news_row, parent, false);
        return new DonorListViewHolder(v);
    } else {
        v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.progressbar_item, parent, false);
        return new ProgressViewHolder(v);

    }

}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof DonorListViewHolder) {

        BlogPosts item = blogPostsArrayList.get(position);

        Constants.showLogTag("" + item.getPostId());

        ((DonorListViewHolder) holder).title.setText(item.getPostHeading());
        ((DonorListViewHolder) holder).category.setText(item.getCatagoryId()+"");
        ((DonorListViewHolder) holder).time.setText(getTime(item.getDateReported()));
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        String baseUrl = settings.getString(Constants.BASE_URL, Constants.BASE_URL);
        Picasso.with(context).load(baseUrl + item.getPhoto350())
                .fit().centerCrop().into( ((DonorListViewHolder) holder).blogImage);

    } else {
        ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
    }
}



@Override
public int getItemCount() {
    return blogPostsArrayList != null ? blogPostsArrayList.size(): 0;
}

@Override
public int getItemViewType(int position) {
    return blogPostsArrayList.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}

public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
    this.onLoadMoreListener = onLoadMoreListener;
}

}

First of all i would move out the onClick listener from the viewholder. Set it on the view in the onCreateViewHolder. Create a final instance of the view holder, set the click listener on the view and from there you can use the viewholder's getAdapterPosition method.

However I would suggest for you to try to clean up the adapter because it's not well written. You should not have static context in the adapter at all. In best cases not even a context. You can use view.getContext() to get a context.

Based on your code the fix should be something similar to this:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    View v;
    if (viewType == VIEW_ITEM) {
        v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.news_row, parent, false);
     final DonorListViewHolder viewHolder = new DonoerListViewHolder(v);
     v.setOnclickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                  try {
            RecyclerAdapter blogsListRecyclerAdapter = new RecyclerAdapter();
            BlogPosts details;
            details = blogPostsArrayList.get(viewHolder.getAdapterPosition());
            Intent i = new Intent(context, ActivityNewsDetail.class);

            context.startActivity(i);
        } catch (Exception e) {

        }
       }});

        return viewHolder;
    } else {
        v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.progressbar_item, parent, false);
        return new ProgressViewHolder(v);

    }

}
  • Put your context into constructor
  • Create interface class to handle clicks
  • Implement your interface in activity/fragment where you initialised adapter and handle click actions

I will show you what i've done in my app (I use Butterknife and Lambdas here):

public class PhotoFeedAdapter extends RecyclerView.Adapter<PhotoFeedAdapter.FeedViewHolder>  {

private List<GetPhotographsData> historyRides;
PhotoFeedAdapterListener photoFeedAdapterListener;

public PhotoFeedAdapter(PhotoFeedAdapterListener photoFeedAdapterListener, List<GetPhotographsData> historyRides) {
    this.photoFeedAdapterListener = photoFeedAdapterListener;
    this.historyRides=historyRides;

}

@Override
public FeedViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    return new FeedViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.feedlist_item,parent,false));
}

@Override
public void onBindViewHolder(FeedViewHolder holder, int position) {

    GetPhotographsData tm = historyRides.get(position);

    Glide.with(AppSingl.getAppSingl())
            .load(tm.getPhotoUrl())
            .into(holder.feed_img);

    Glide.with(AppSingl.getAppSingl())
            .load(tm.getUser().getUserPhoto())
            .into(holder.img_avatar);

    holder.tv_username.setText(tm.getUser().getUserName());
    holder.tv_signername.setText(tm.getSigner().getSignerName());



    holder.feed_img.setOnClickListener(v -> {
        if (photoFeedAdapterListener!=null)
            photoFeedAdapterListener.onPhotoClicked(position);
    });

    holder.tv_username.setOnClickListener(v -> {
        if (photoFeedAdapterListener!=null)
        photoFeedAdapterListener.onOwnerClicked(position);
    });

    holder.img_avatar.setOnClickListener(v -> {
        if (photoFeedAdapterListener!=null)
            photoFeedAdapterListener.onOwnerClicked(position);
    });

    holder.tv_likes.setText("55 лайков");
    holder.tv_comments.setText("20 комментариев");

}

public GetPhotographsData getItemAtPosition(int position){
    return historyRides.get(position);
}


@Override
public int getItemCount() {

    return historyRides.size();
}



public class FeedViewHolder extends RecyclerView.ViewHolder {

    @BindView(R.id.feed_img)
    SquareImageView feed_img;

    @BindView(R.id.img_useravatar)
    CircleImageView img_avatar;

    @BindView(R.id.tv_username)
    TextView tv_username;

    @BindView(R.id.tv_signername)
    TextView tv_signername;

    @BindView(R.id.tv_likes)
    TextView tv_likes;

    @BindView(R.id.tv_comments)
    TextView tv_comments;

    public FeedViewHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }
}}

}

public interface PhotoFeedAdapterListener {

void onOwnerClicked(int position);

void onSignerClicked(int position);

void onOptionsClicked(int position);

void onPhotoClicked(int position);}

Not necessarily the ViewHolder classes in the Adapter Class need to be static . Also there is no need to make different ViewHolder classes for different views.

Following code may help.

public class NewsFeedAdapter extends RecyclerView.Adapter<NewsFeedAdapter.ViewHolder> {
JSONArray posts;
Context mContext;


public NewsFeedAdapter(Context context, JSONArray posts) {
    mContext = context;
    this.posts = posts;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    switch (viewType) {
        case 1:
            return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.row_question, parent, false), viewType);
        case 2:
            return new ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.row_poll, parent, false), viewType);
    }
    return null;
}

@Override
public int getItemViewType(int position) {
    try {
        JSONObject post = posts.getJSONObject(position);
        return Integer.parseInt(post.getString("p_type"));
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return super.getItemViewType(position);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    try {
        switch (holder.viewType) {
            case 1:
                //Question
                JSONObject post = posts.getJSONObject(position);
                holder.content.setText(post.getString("content"));
                holder.upvote.setText("UPVOTE(" + post.getString("upvote") + ")");
                holder.downvote.setText("DOWNVOTE(" + post.getString("downvote") + ")");
                break;
            case 2:
                JSONObject poll = posts.getJSONObject(position);
                holder.poll_content.setText(poll.getString("content"));
                break;
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

}

@Override
public int getItemCount() {
    return posts.length();
}

public String getUserType() {
    return mContext.getSharedPreferences("user_details", Context.MODE_PRIVATE).getString("type", "");
}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    TextView comment, upvote, downvote, content;
    LinearLayout ll_content, ll_upvote, ll_dvote, ll_comment;
    int viewType;
    TextView poll_content, tv_respond;

    public ViewHolder(View itemView, int viewType) {
        super(itemView);
        this.viewType = viewType;
        switch (viewType) {
            case 1:
                comment = (TextView) itemView.findViewById(R.id.tv_comment);
                upvote = (TextView) itemView.findViewById(R.id.tv_upvote);
                downvote = (TextView) itemView.findViewById(R.id.tv_dvote);
                content = (TextView) itemView.findViewById(R.id.tv_content);
                ll_content = (LinearLayout) itemView.findViewById(R.id.ll_content);
                ll_content.setOnClickListener(this);
                ll_upvote = (LinearLayout) itemView.findViewById(R.id.ll_upvote);
                ll_upvote.setOnClickListener(this);
                ll_dvote = (LinearLayout) itemView.findViewById(R.id.ll_dvote);
                ll_dvote.setOnClickListener(this);
                ll_comment = (LinearLayout) itemView.findViewById(R.id.ll_comment);
                ll_comment.setOnClickListener(this);
                break;
            case 2:
                poll_content = (TextView) itemView.findViewById(R.id.tv_poll_content);
                tv_respond = (TextView) itemView.findViewById(R.id.tv_respond);
                poll_content.setOnClickListener(this);
                tv_respond.setOnClickListener(this);

        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ll_content:
                Bundle bundle = new Bundle();
                Intent intent = new Intent(mContext, PostDetailsActivity.class);
                try {
                    intent.putExtra("postdetails", posts.getJSONObject(getLayoutPosition()).toString());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                mContext.startActivity(intent);
                break;
            case R.id.ll_upvote:
                try {
                    upvoteThePost(getLayoutPosition());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM