0

At first I assigned clickListener in OnBindViewHolder and it was working just fine but as many here on stackoverflow advised that it is not a good practice and it is better if I handle all my click listener logic in ViewHolder. Now in OBVH I used holder's position to get current item' position but in VH I didn't even use any position or getAdapterPosition and still I am getting correct item position.

ViewHolder:

 private class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private ImageView mImageView;
    private TextView mTextView;
    private Results mResults;

    private NewsHolder(View itemView) {
        super(itemView);
        mImageView = itemView.findViewById(R.id.news_image);
        mTextView = itemView.findViewById(R.id.news_headlines);
        itemView.setOnClickListener(this);
    }

    public void bind(Results results){
        mResults = results;
        mTextView.setText(mResults.getWebTitle());
        String picture = mResults.getFields().getThumbnail();
        if (!picture.isEmpty()) {
            Picasso.get()
                    .load(picture)
                    .placeholder(R.drawable.display)
                    .resize(200, 200)
                    .into(mImageView);
        } else {
            Picasso.get()
                    .load(R.drawable.display)
                    .resize(200, 200)
                    .into(mImageView);
        }

    } 

    @Override
    public void onClick(View view){
        String itemWebUrl = mResults.getWebUrl();
        Uri currentItemUri = Uri.parse(itemWebUrl);
        Intent websiteIntent = new Intent(Intent.ACTION_VIEW, currentItemUri);
        view.getContext().startActivity(websiteIntent);
    }
}

OnBindViewHolder

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

        try {
            Results results = mResults.get(position);
            holder.bind(results);
        } catch (Throwable throwable) {
            Log.d(TAG, " " + throwable);
        }
    }

Results model class:

public class Results{

@SerializedName("id")
@Expose
public String id;

@SerializedName("sectionId")
@Expose
private String sectionId;

@SerializedName("webTitle")
@Expose
private String webTitle;

@SerializedName("webUrl")
@Expose
private String webUrl;

@SerializedName("fields")
@Expose
private Fields fields;

public String getId(){
    return id;
}

public String getSectionId(){
    return sectionId;
}

public String getWebTitle(){
    return webTitle;
}

public String getWebUrl(){
    return webUrl;
}

public Fields getFields(){
    return fields;
  }
}

Is it possible to get correct item position without getAdapterPosition()?

Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
white_wolf
  • 13
  • 4
  • "in VH I didn't even use any position or getAdapterPosition and still I am getting correct item position." – I don't see that you're currently using any kind of a position value anywhere in `NewsHolder`. If you're asking why you're getting the correct data there otherwise, it's because you've set the corresponding `Results` object in `NewsHolder` from `onBindViewHolder()`. – Mike M. Aug 19 '18 at 08:57
  • I had the impression that getAdapterPosition() is the only way to get item's position in the Recyclerview. – white_wolf Aug 19 '18 at 14:14
  • That's how you would get the position within a `ViewHolder`, but you don't need it there, because you're already attaching the necessary data via the `Results` object. – Mike M. Aug 19 '18 at 14:17
  • @MikeM. Is this a good alternative to creating a separate onClickListener Interface for getting item position? – white_wolf Aug 23 '18 at 17:15
  • I'm not exactly sure what you're asking. I mean, you still have to implement an `OnClickListener` _somewhere_. If you're asking if the one you have is better than calling back to the `Activity`, not necessarily. You generally want to let the `Activity` handle things like starting other Activities. However, if you were to create an interface to do that, you still wouldn't necessarily need the position. Since you have the `Results` right there in the `ViewHolder`, you could just pass the `Uri`; e.g., `public interface OnRecyclerClickListener { void onRecyclerClick(Uri uri); }`. – Mike M. Aug 23 '18 at 17:26
  • Some answers at SO suggested to create a separate interface clicklistener if my **ViewHolder** didn't have any results object and instead of creating a helper method for binding objects, I would have done the binding in **OnBindViewHolder**. If you don't mind me asking, what is the alternative to parse the uri and open a webpage on chrome or any other browser on my device by using Fragments? – white_wolf Aug 23 '18 at 17:38
  • It would be like is shown in [this answer](https://stackoverflow.com/a/40584425), except the `ItemClickListener` interface's `onItemClick()` method would have a `Uri uri` parameter, and you'd call `startActivity()` with it in `MainActivity`'s `onItemClick()` implementation. – Mike M. Aug 23 '18 at 17:43

1 Answers1

0

You are already getting proper Results object using position, which is used in NewsHolder. So nothing has to be modified.

Results results = mResults.get(position);
holder.bind(results);
Gokul Nath KP
  • 15,485
  • 24
  • 88
  • 126