Office Hours — Today, January 12

Saturday, January 9

Mark M.
has entered the room
Mark M.
turned on guest access
Jan 12
8:45 AM
ani
has entered the room
8:50 AM
Mark M.
hello, ani!
how can I help you today?
ani
Hey Mark, happy 2021
Mark M.
Happy 2021 to you as well!
ani
I have something related to Recycler view with paging, updating an item property. Wanted to pick you brain on a problem around that.
View paste
Consider the following user-case:
A user item with properties 
name : String,
id(unique) : String,
isLikedByMe : Boolean,
similarUsers: List[users]
View paste
I am showing paged list of user objects, coming from a page keyed datasource in the recycler view.
When a user item in the list is tapped, a bottom sheet(user detail sheet) with certain peak height is opened, that shows these items in a bit more detail to the viewer.
It also has an option to say, like the user tap one, you like the user, tap again, you remove your like.
What is a decent way to like a user on user detail sheet on the and update the status of isLikedByMe field on the users’ list partially visible behind the detail sheet?
I would imagine calling notifyItemChanged(position, payload) somehow but not sure how it fits in the context of paging source and paged lists.. Additionally, I won’t necessarily have position in the users’ list on user detail screen.
Please let me know if the description isn't clear enough..
Mark M.
If we temporarily ignore paging for the moment... the viewmodel behind your detail sheet could tell the user repository about the like/unlike action. The repository would both update your persistent data store (presumably a Web service here) and emit a fresh user object. Your fragment(?) that has the RecyclerView would get that fresh user object and update its UI accordingly (e.g., ListAdapter and DiffUtil.ItemCallback).
paging makes this more complicated
which version of the paging library are you using?
8:55 AM
ani
currently paging version 2
Mark M.
OK. I never used that. The API is similar to Paging 1, and I never successfully used that for anything other than Room. For Kotlin developers, Paging 3 is nice, though it is only in alpha right now.
ani
If I were not using paging, I could just emit a list of 1 item, because it has a unique ID, the diffutil callback would. update the appropriate user item. Did I get that right?
Mark M.
no, you would emit a list of all items, with the one item updated, and DiffUtil.ItemCallback and ListAdapter would arrange to only affect the one row of your RecyclerView that was really affected
ani
got ya, thanks
How would you deal with this in paging 3? I may be able to draw some similarities with that.
9:00 AM
Mark M.
I have not found a clean pattern for it, other than to update the data source (e.g., Web service) and tell paging to reload. A not-very-clean pattern is to get an object into the main fragment's viewmodel that represents a "local override" of a model object from paging -- when we see paging try to return that model object (e.g., via ID), we replace it with the local override.
I wound up doing that latter approach on one project, where we wanted an "optimistic UI" -- we wanted to assume that the Web service update would succeed and just revise the UI to reflect the change (in your case, reflect the new or removed "like").
frankly, it's a hack
however, it was a bit of a "rush job", and we did not have time to figure out anything cleaner
ideally, Google documents some patterns for this, as what you need (and I needed) seems reasonably commonplace
9:05 AM
ani
In the later approach, how would you be able to update the row behind the user detail sheet open. Since bind to viewholder will not be called if the item is already present on the screen..
thank for sharing context around that answer :)
Mark M.
we are asking something to refresh -- I am trying to track down exactly what
though, based on those docs, that may not be the best answer
9:10 AM
ani
let me take a look, thanks for the link Mark
View paste
One way I found much simpler* and relatively clean is to use a backing database and watch for changes on it. courtesy live data <PagedList<>>
Works pretty decently. 
I cannot use this approach since there can be multiple user list screens added to the stack
User List  User Detail User List User Detail ...
Since user detail has a list of users that can take you to another similar list..
9:15 AM
Mark M.
I agree that working with local data stores is easier in general, let alone with the Paging library
and, it fits one of Google's preferred patterns, where all immediate interaction is with a local data store and the Web service simply populates that data store
that's just not a simple architecture to implement in general and may be impractical (or against policy) for many situations
ani
ya, I agree. In the case of same Entity, it breaks down like it did in my case. I can only paginate on once screen. Other screen will have to have another entity name. Since Room doesn't have dynamic table names, I cannot do room as paging source in this particular user-case.
9:20 AM
ani
View paste
what are your thoughts on updating the property in the item object itself?
Say, I set the property isLikedByMe to true in the user object returned by getItem(position) in the paging adapter itself..
User taps on selected item, takes it to the user details screen. I pass the user item object to this screen. If a change is observed in user isLikedByMe property, the common viewModel will register that and call notify item range changed for the items currently visible on screen.
It will update multiple items, but not all.
Another hack though.
Mark M.
the problem is that you should lose that object if the user scrolls the list
and Paging will deliver you a fresh object that may or may not have your data change
(assuming that I understand your proposal correctly)
9:25 AM
Mark M.
that was part of the reason why I put our "local override" in the viewmodel, so we could arrange to feed in our own local copy of the model object even if Paging wanted to give us something else
that's easy to do with Paging 3 -- with Paging 2, you might need to wrap your PagedList in a decorator that could do the replacement
ani
Ya, you understood it correctly. Although, it is the object delivered by paged list that I modify the property on. So scrolling or not shouldn't the same object be returned. I am thinking paged list will return the original object and not a deep copy :)
thanks, I ll consider the wrapping/decorator suggestion
9:30 AM
Mark M.
I am sorry that I did not have a better solution to offer you
and... that's a wrap for today's chat
the transcript will be posted to https://commonsware.com/office-hours/ shortly
the next chat is Thursday at 7:30pm US Eastern
have a pleasant day!
ani
has left the room
Mark M.
turned off guest access

Saturday, January 9

 

Office Hours

People in this transcript

  • ani
  • Mark Murphy