Danny Hambourg Danny Hambourg - 7 months ago 18
Java Question

Android - Recycler View with GCM

I am using a

RecyclerView
that show results that come from
GCM
callbacks. The
RecyclerView
has a custom adapter a method add, there is also a progress bar that updates using an asynctask.

Message recieving over
GCM
that works fine:

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.add(new ResultRecord("asf", 89, 1000));
}
});
}
};


Add method in the custom adapter:

public void add(final ResultRecord result) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
results.add(0, result);
notifyItemInserted(0);
}
});
}


The problem is that the method add called and nothing happens on the UI. The method add called and then onBindViewHolder and the recycler view does not update. Only when the progress bar is finished the
RecylcerView
is getting update with all the
ViewHolder
s that has been added before.

I have checked if the add method works from the
onCreate
method and it worked fine. Maybe this problem is related to threading.

Answer

You have a Threading problem here.

Your code is based on ArrayList, which isn't Thread-Safe. You are calling the "Add" method from event, which called probably from multiple threads.

You have to synchronize your code. Something like this:

private final ReentrantLock lock = new ReentrantLock();
public void add(final ResultRecord result) {
    lock.lock();
    try {
        AddNotThreadSafe(result); // Only one thread add in same time. Now is safe for executing. 
    } finally {
        lock.unlock();
    }
}

Now, move your original Add code to separated method called AddNotThreadSafe.

This should work. :)