With ListView
we have had a good native pattern to map some data from db to list:
DB
-> ContentProvider
-> CursorLoader
-> CursorAdapter
-> ListView
This approach was good in terms of data layer separation, performance and automatic data updates. But this pattern doesn't really fit new RecyclerView
. There are some approaches to mimic old behavior:
Using the recyclerview with a database
But there is a problem with using old style notifyDataSetChanged
with RecyclerView
. It can't use ItemAnimator features, it loses scrolling position, and it's just ineffective.
So, how we can benefit from finegraned change notifications while using DB wrapped in ContentProvider
? Cursor
is static, and to get new data from it we need to get new Cursor
. So, it seems that we will need an custom intermediate data layer, which will merge data from Cursors and expose the List
of entities to RecyclerView.Adapter
. Also, we will have to manually map ContentObserver
onChange()
events to RecyclerView notifications. This also means that we will have to get rid of CursorLoader. That is an incredible amount of work for such basic task.
Is there any better solution?
You can use the DiffUtils class to compute the differences between the old and new cursor.
When using it you just need to implement two methods :
areItemsTheSame()
to know if two items represent the same logical item (even if the content is different). Usually you would base the answer on an identifying field of your item;areContentsTheSame()
to know if two items representing the same logical item have unmodified content.Once the differences are computed, you can then just apply it to your adapter and it will automatically call the notifyItemChanged()
, notifyItemInserted()
or notifyItemRemoved()
accodingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With