Skip to content
Advertisement

Android recycle view update sort list with concurrency issue

I have a sorted list I would like to use to hold objects for maintaining a recycleview as usual.

The api I am interfacing with passes me updates through an interface callback using multiple threads. This api can add, remove or update object state. When the app opens there is a flurry of adds, removes and updates. Then it slowes down to some degreee. This is a reverse of the typical database paradigm where the UI updates faster than the data to one where the data updates faster than the UI

This seems to be an issue with the sortedList in android for several reasons.

  1. adding an item to sortedlist must be done on UI thread if updates to list are going to fully execute without simply adding to the list and swallowing the error in a background thread when trying to show the update

  2. to change an object state you must first get the index. then get the item. if your multithreading then you get index errors due to race conditions and pull the wrong object

  3. you can affect a list item object’s state in a background thread but this still relies on a call to recalculate() or updateitem() type calls. this leads to reycleview is computing layout errors

Question: Which design pattern would you use to solve this issue? Below are some of my ideas

solutions that seem bad

  1. Swallow errors and use a timer to call notifydatasetchanged(). This really eliminates the purpose of using the sorted list.

  2. Collect updates in another list and do batch updates when size() > someNumber or some timer. why bother using sortedlist

solution that seems good

  1. add all object into a concurrent hashmap. This solves the threading and update issues. But I still need to present a sorted list to the UI. This means batching add and remove for the sorted list. Then also calling notifydatasetChanged() from time to time to handle object state updates

  2. My fantasy solution that maybe exists already is to use an object that holds a concurrent sorted list where I can add, remove and update from a background thread and also bind to a recycleview adpater.

Advertisement

Answer

My solution is to hold updates in a buffer which can only fire after a time delay. Then putting the update objects into both a concurrent hashmap for easy object retrieval as well as a sortedlist for easy ui display

The api calls this method. I have another version that can run off the ui thread by simply detaching the adapter in sortedlist callbacks.

public void onResult(Object object) {
    
        if ( !currentlyProcessing && System.currentTimeMillis() > (lastBatch + delay)) {

            currentlyProcessing = true;

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    easyChatList.beginBatchedUpdates();

                    while (batchBuilder.size() > 0){
                        performBatch(batchBuilder.remove(0));
                    }
                    easyChatList.endBatchedUpdates();

                    lastBatch = System.currentTimeMillis();
                    currentlyProcessing = false;
                }
            });
        }
}

The performbatch() handles a single update. If the object is new it puts it into a concurrent hashmap with its id as a key. Then adds it to the sortedlist. When an update occurs I pull the object from the hashmap, do the update and add it to the sortedlist. The sortedlist api then replaces the old object and updates the sort order.

edit:this does have a slight drag according to androids skipped frames warning. You can detach the adapter from the sortedlist and do updates on a worker thread but I’m not sure if that has any value as this is working alright for now.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement