How to get Adapter position in the RecyclerView - android

In the list view, I have the object of my POJO class so if I want to fetch an object's position in the list view it can get by below code
mAdapter.getPosition(object)
but I cannot find any solution to get an Adapter position with the help of my object in the recyclerview
Please help me for the same.

You can't get the position via mAdapter.getPosition(object) in case of recycler view. But if you really want the position via object then, you can get it by:
array.indexOf(obj);
here array is your array list which content you are setting to the recycler view.

Use last param of onBindViewHolder() method of Adapter class for get position
public void onBindViewHolder(#NonNull FavourtieViewHolder favourtieViewHolder, int position) {
// like this
POJO obj=list.get(position);
// using Adapter holder class object you can also get position
int pos=favourtieViewHolder.getAdapterPosition();
}

Related

Recyclerview.notifyItemInserted() duplicates the list item

I have a requirement, where I should download the ad item while scrolling and update the list. Since calling notifyDatasetChnaged(), resets everything, I'm calling notifyItemInserted(position). But, calling this duplicated the items in the list. I found that there are no repeated items in the list. But after calling notifyItemInserted, it duplicates the item. I'm not getting how to resolve this issue. This what I'm doing:
mNewsList.add(mPreviousAdPosition, newsItem);
mAdapter.notifyItemInserted(mPreviousAdPosition);
If I call, it works properly, there are no repeated items. But I don't want my list items to recreate. What can be the issue ?
I had the same problem for exactly the same use case, the solution is:
Implement this method in your Adapter :
#Override
public long getItemId(int position) {
//Return the stable ID for the item at position
return items.get(position).getId();
}
Call this method in the Constructor of your Adapter :
//Indicates whether each item in the data set can be represented with a unique identifier
setHasStableIds(true);
You can add the object at the end of the array with each object having a position along with it where it needs to be shown in the recycler view. Sort this array on the basis of position before calling notifyItemInserted(position). In this way only required data will be drawn.I have recenlty followed this approach and works very well with dynamic sections added in between in recycler view.
You should add the item at the end of the list.
mNewsList.add(newsItem);
and then notify like this.
mAdapter.notifyItemInserted(mNewsList.size()-1);
Create a temporary list and add items as mentioned below:
List<YourModel> mTmpList = new ArrayList<YourMdel>();
//add items (from 0 -> mPreviousAdPosition) to mTmpList;
for(int i=0; i<mPreviousAdPosition; i++) {
mTmpList.add(mNewsList.get(i));
}
//add item at mPreviousAdPosition
mTmpList.add(newsItem);
//add remaining items and set i<=mNewsList.size() because we ha
for(int i=mPreviousAdPosition; i<=mNewsList.size(); i++) {
mTmpList.add(mNewsList.get(i - 1)); //because we have added item at mPreviousAdPosition;
}
mNewsList = mTmpList;
mAdapter.notifyDataSetChanged();
You code should be written like this:
public class RecyclerViewAdapter extends RecyclerView.Adapter{
...
public void addData(int position, Item newsItem) {
mNewsList.add(position, newsItem);
notifyItemInserted(position);
}
...
}
and then you need to call the fun addData

Issue refreshing a view of a row in recyclerview

I want to update a view of the recyclerview when a notifyItemChanged has been called. The thing is that I don't want to refresh the entire row but only the view of the row. (to avoid the blinking effect of the row)
There is a method called notifyItemChanged(int, payload obj).
Can I use that to achieve that? If so how to do it?
Finally I found how to update only the specific view of a row in RecyclerView.
(1) Override onBindViewHolder(Recycler.ViewHolder VH, int position, List payloads) in the adapter
(2) Inside that onBindViewHolder method,
if(payloads != null && !payloads.isEmpty() && (payloads.get(0) instanceof customObject)){
// update the specific view
}else{
// I have already overridden the other onBindViewHolder(ViewHolder, int)
// The method with 3 arguments is being called before the method with 2 args.
// so calling super will call that method with 2 arguments.
super.onBindViewHolder(holder,position,payloads);
}
(3) So to notify data change and update the view, need to call the notifyItemChanged(int position, Object payload). Need to pass the customObject(model which holds the data) as the payload object.
adapter.notifyItemChanged(i, obj);
Note : Need to disable the RecyclerView's ItemAnimator(By default it is enabled). Otherwise payload object will be empty.
recyclerView.setItemAnimator(null);
or
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
UPDATE: I used this method recently without disabling the ItemAnimator. So no need to disable ItemAnimator. - (recyclerview-v7:25.4.0)
for further reference
You can use this to get the view of updated item:
View v = recyclerView.getLayoutManager().findViewByPosition(position);
if (v != null){
//update your view
}
Let's say you have an ArrayList of items, and it is fed to the RecyclerView adapter. Let it be something like this.
List<String> items = new ArrayList<>();
RecyclerAdapter adapter = new RecyclerAdapter(items);
recyclerView.setAdapter(adapter);
Now as I can see you want to insert items into the RecyclerView and call notifyItemChanged(int position) method to add only the single item.
For this let's say you have changed the value of item in position 0. That's the first item in the list.
Now the proper usage of the method notifyItemChanged(int position) will be
adapter.notifyItemChanged(0);
This means, the adapter will update the recyclerview with the new value in 0 position.

RecyclerView Adapter :OnBindViewHolder

Why do we use something like this to populate the recyclerview with data? Can't we just create a simple array of string like String[] titles and display them, like in ListView?
List< Information> data
public void onBindViewHolder(MyViewHolder holder, int position) {
Information current = data.get(position);
holder.title.setText(current.title);
holder.icon.setImageResource(current.iconId);
}
I recently watched a video on how to work with recyclerview and I can't understand why we have to create another class of information and then again create its array inside onBindViewHolder to show data.
Can anybody help me understand this code?
If you take a look at this example by google, they used an array dataset to populate data in RecyclerView.
Take a look at Google's docs:
Called by RecyclerView to display the data at the specified position. This method should update the contents of the itemView to reflect the item at the given position.
Note that unlike ListView, RecyclerView will not call this method again if the position of the item changes in the data set unless the item itself is invalidated or the new position cannot be determined. For this reason, you should only use the position parameter while acquiring the related data item inside this method and should not keep a copy of it. If you need the position of an item later on (e.g. in a click listener), use getAdapterPosition() which will have the updated adapter position. Override onBindViewHolder(ViewHolder, int, List) instead if Adapter can handle effcient partial bind.
String [] title ;
int [] imageID;
onBindViewHolder(MyViewHolder holder, int position) {
Information current = data.get(position);
holder.title.setText(title [position]); holder.icon.setImageResource(imageID [position]);
}

RecyclerView android: Getting an item at a particular position

Is there any way to get an item of the RecyclerView at a particular position outside the adapter. e.g in ListView we could do:
listView.getItem(position);
Can we do this with RecyclerView ? and also is the order of provided data list maintained ?
You can add your own method to RecyclerView or I would suggest the RecyclerView.Adapter itself.
For instance, for ListView, you have:
#Override
public Object getItem(int position) {
return listData.get(position);
}
You can add the same thing to your RecylcerView.Adapter or access it another way by adding a simple method to your RecylcerView.Adapter:
public List<Model> getList() {
return this.mModel;
}
Use it like this:
recyclerView.getAdapter().getList().get(position)

Implementing OnItemClickListener() for a dynamic GirdView/ListView

That GridView adapter creates ImageView from a layout.
All images are downloaded from URLs respect to the database item IDs where the ID is got from a JSONArray.
Let say, the view is now showing items with
ID: 1,3,4,7.
As the GridView items are dynamic, the position (starting from 0) cannot really identify my item on the GridView.
Is there any other ways to identify that image from the database item IDs?
public OnItemClickListener ClickListner = new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Toast.makeText(getApplicationContext(),
// ""+position, Toast.LENGTH_SHORT).show();
//Identification code for the item to be added here
Intent view =
new Intent(main.this, View.class);
view.putExtra("ID", id);
//expected to have an ID equal to database item ID
startActivity(view);
}
};
First option (the nice way)
You keep a reference to your adapter (or you get it by calling parent.getAdapter() and then cast it)
In your adapter make sure that you've overridden getItem(position) to return the object you used to fill up your adapter (probably something like return arrayList.getItem(position)if you used BaseAdapter)
On the adapter you call getItem(position) and this will give you the very same object, so you should have all the info you need now
Second option (easy way out)
You can put info in the gridviewitem's view using setTag()
then in onItemClick you call getTag() and there you have your unique id
You can use a POJO class to set the URL and ID of Image in that class and create and ArrayList for the same and passing that to the Adapter class. By, doing this you will bind your ImageView and the ImageID from your database. And, then inside onItemClick() you can simply use
POJO pojo = listview.getAdapter().getitem(position);
int id = pojo.getId();

Categories

Resources