简体   繁体   中英

What's the proper way of notifying a RecyclerView adapter about changes in non-visible items?

I'll try to be as specific as possible. I have a cursor-backed RecyclerView adapter. I'm using LoaderManager callbacks to get updates when the DB values change, which gives me a new cursor. I'm then comparing the new cursor with the one the adapter currently holds to figure out what's changed, switching out the old one with the new one in the adapter, and then calling the appropriate notifyItem(Range)Inserted/Changed/Removed() functions. This works great, but there are some places I'd like to use it that can have some pretty big cursors, so I'm hoping to optimize it by figuring out which items are visible using the layout manager and then only checking those items in the cursor for changes instead of checking every single row.

Now my question is, let's say I have a cursor with 1000 rows, and my RecyclerView is showing say rows 0-10. I can go through the cursors, checking the items at index 0-10 for changes/additions/deletions and call the appropriate notify() functions as I'm currently doing, but what about the non-visible items? Do I have to notify the adapter that there may be changes in those rows or can I safely just ignore them and it will just use the updated data when those rows get bound?

Edits for clarity, my code flow is like this:

My adapter holds a cursor, getItemCount just returns cursor.count() and the ViewHolder binding code is along the lines of cursor.moveToPosition(position) followed by some things like ViewHolder.setFoo(cursor.getString(BAR))

When something changes in the DB, the LoaderManager callbacks call onLoadFinished with an updated cursor, and then that calls adapter.changeCursor(newCursor)

changeCursor basically iterates over the old and new cursor to check what's changed. That works fine, but if the cursor is very large it might take some time to loop the whole thing, so I was hoping to be able to skip everything except the visible items. If I do that, changes work fine since onBindViewHolder will use the updated cursor, but if a (non-visible) row is added or deleted and I don't call notifyItemInserted/Removed , the adapter doesn't know about it and doesn't handle it properly, which leads me to believe that I can't do this optimization, I have to just loop the whole thing to find added/removed rows

Your intuition is correct.

You don't need to concern yourself with the non-visible items. When the LayoutManager eventually places them on-screen, you will get a call to bindViewHolder in the adapter. It is here where you'll reflect the current state of the adapter (which has your cursor) in your view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM