I'm using pagination to get data from network as the only datasource. In the PagedListAdapter I have a button which on click will update the data in the network now I need to get the updated data and change the view for that item. How do I do that?. Is there a way to achieve this without using db?...
lets say I have a Model named Post and it has a field named isSaved. so what I'm doing rt now is when I click the save button in the PagedListAdapter view then I'm calling an api to update that field ..so now I want to get the updated value for that particular post item and change the button's text as saved....since i'm using adapter.submit(listOfPost), the list is the same so DiffUtil itemCallback isn't being called...What should I do??
Suppose when you pass page 1 then take example its returning you 30 items. So all you have to check here is whether recyclerview can scroll vertically or not. If not then increase the page number and call api method again.
And to check whether recyclerView have more item to scroll below method will help you.
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
if(!mRecyclerView.canScrollVertically(1)){
// search the next page
searchNextPage();
}
}
});
For more details this link will be helpful for you: https://github.com/mitchtabian/RestApiMVVM
Related
Let's say I'm getting data from an API which gives an array of 20 items at a time with a next_page attribute which gives the next set of 20 items and so on, so what i wanna do is, i want to make a lazylist of first 20 items and when the user scrolls all of the 20 items, i wanna get some callback or some way to know that lazylist haa reached its end so i could make an API call to fetch the next set of 20 items and append it on the allItems list and then somehow make my lazylist bigger behind the scenes, so now it have 40 items and user can scroll even further.
On RecyclerView it was very easy to implement that for me, i just needed to add an onScrollStateChanged() listener and add a simple check like:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(1) && newState==RecyclerView.SCROLL_STATE_IDLE) {
Log.d("-----","end");
}
}
});
I wanna know how can I do the same in jetpack compose basicall
You have to make 1 master list and 1 list that came from api once api return data.
You have to insert that data to master list and send that list to recycler view adapter when it came to last position of recycler view call api and add another data to master list and so on...
There is a situation where I have to scroll the recyclerview to last position. The problem starts where I am using Paging 3. I don't know what is the proper way to do it every time I submit data to adapter. by the way I have to say that I do not submit data once, but for example every time user submits a new comment to backend I have to get the new list from server and submit it.
This is what I tried. that's how I observe data:
private fun observeComments() {
exploreViewModel.commentsLiveData.observe(viewLifecycleOwner) { comments ->
commentsAdapter.submitData(viewLifecycleOwner.lifecycle, comments)
}
}
And this is how I tried to scroll the recyclreview to last item:
commentsAdapter.addLoadStateListener { loadStates ->
if(loadStates.refresh.endOfPaginationReached){
if(commentsAdapter.itemCount>1)
binding.rvComments.smoothScrollToPosition(commentsAdapter.itemCount-1)
}
}
I also set app:stackFromEnd="true" to recyclerview but this is not useful. whenever I submit a new comment and get the list, recyclerview scrolls to the middle, I thinks it scrolls to the first pages end. but I want it to be scrolled to the end of the list.
Any help or suggestion would be appreciated.
You can implement PagingSource.getRefreshKey() to control the key passed to .load() after invalidation and set initialKey in Pager() to control the key passed to initial call of .load().
Since your list is paginated, scrolling to the end doesn't work because you would need to sequentially load all pages until you get to your desired position, so instead the better strategy is to start loading from where you want the user's scroll position to start, then let paging prepend pages as they scroll back up.
I want to update one item calling asynchronous call to server API inside onBindViewHolder. I send item at position + position into the callback. Response call arrives in 20 seconds into callback funcion. Into the callback function is returned response and position. Then I call notifyItemChanged(pos, response). And inside payload onBindViewHolder I update item on that position and its View. Problem is that if async request takes 20 seconds and user will scroll quickly throught RecyclerView it will update wrong item View because that view at position could be unbound or could be bound to other item from list.
Is there any way how to track which item at which position is unbound to cancel request? I have to update this one info after adapter is created, because if I will do that before, user will not see any recyclerView item for almost 2 minutes till my list is ready. (only this one call is taking so long).
I wouldn't pass the position as context. I would pass an identifier. Could be an internal integer as id or something. Then you can easily determine which id's are currently visible on the screen and see if that list contains the id of the calback.
I am not sure about your question, but you could work onto your items directly in your adapter.
Then you do:
Adapter adapter = new BaseAdapter(newDataset);
recyclerView.setAdapter(adapter);
recyclerView.notifyDataSetChanged();
Otherwise, if your really work on views rather than dataset, you can do this:
in your adapter:
create a View array
create a custom function View getViewAtPos(int pos)
check if your view is visible in your current scrollview (here)
I have a recycler view I want to update one attribute of each item after the initial creation to provide the user with a nicer experience. I would like to do this asynchronously as it takes time to get the data.
How do you iterate over the items in a recycler view and subsequently update. I moved from listview to recycler because it has a the method NotifyItemChanged.
So Ideally I would like to do
void OnRefresh(IList<data> data)
{
Data = data;
NotifyDataSetChanged();
Task.Run(() => UpdateAllAttribute1Fields());
}
void UpdateAllAttribute1Fields()
{
foreach(var myItem in myRecyclerView.Items)
{
UpdateAttribute1(myItem));
}
}
But I do not understand how to access myItems. On windows (sorry), in a listview this would be listview.items I think.
I could save the views OnBindViewHolder but that will be a bit more work.
Thanks all.
You dont need to iterate over all items in recyclerview to update, Just set the RecyclerView to point to your custom data set. And asynchronously update the data set whenever you want. You can then notify the recyclerview that the data in the dataset has changed with the following methods of its adapter (which will automatically update the recyclerview content)
adapterObj.notifyItemChanged(pos) //for one object
adapterObj.notifyDataSetChanged() //for the entire dataset
adapterObj.notifyItemRangeChanged(start, end) //for a range
I've got this RecyclerView, it's showing a list of persons with their names, phones and birthday.
I want to change the color of the item if the person's birthday is today, but I want to know if I should do the verification and change on my RecyclerView's adapter inside the OnBindViewHolder method, or if I should do it inside my activity calling my LinearLayoutManager or calling the item using the RecyclerView.getChildAt() method.
Should I go whit the first option, using the onBindViewHolder?
YES . Should you choose to make changes in the onBindViewHolder().
We'll take a sample:
#Override
public void onBindViewHolder(FeedsViewHolder feedViewHolder, int i)
{
if(d1.feeds.get(i).getFeedContentType().equals("b-day")) // <-- Pointing to the List that contains value, and checks if it equals to a sample string
{
feedViewHolder.n1.setText("Birthday"); // <-- if it equals, party time :D , and sets text to the corresponding TextView in the RecyclerView
}
}
Hope it helps :)