In my application I have multiple ComposedCursorLoaders that have the same query within the same screen (business logic dictates how to filter that data for each view). There's a race condition that happens when data arrives from the server and gets inserted into the database. Here's a scenario when that happens:
1) Data is requested
2) Cursors are initialized and begin the process of querying the ContentResolver for data
3) Data is inserted into db and cursor is notified
4) Since queries for ComposedCursorLoaders happen on the background thread, but the cursor is registered to receive notifications happen on the UI thread, there's a window of opportunity for missed notifications, which is what I saw in my application.
The following is the refactored ComposedCursorLoader which fixes this race condition. The solution is to move the observer registration into the background thread and register the Cursor as soon as it is acquired from the ContentResolver.
@Override
public T loadInBackground() {
final T result;
final Cursor cursor = loadCursorInBackground();
try {
cursor.getCount();
cursor.registerContentObserver(observer);
if (!additionalUrisRegistered) {
ContentResolver resolver = getContext().getContentResolver();
for (Uri notificationUri : notificationUris) {
resolver.registerContentObserver(notificationUri, true, observer);
}
additionalUrisRegistered = true;
}
result = cursorTransformation.apply(cursor);
Preconditions.checkNotNull(result, "Function passed to this loader should never return null.");
if (cursorsForResults.get(result) != null) {
releaseCursor(cursor);
} else {
cursorsForResults.put(result, cursor);
}
} catch (RuntimeException ex) {
cursor.close();
throw ex;
}
return result;
}
In my application I have multiple ComposedCursorLoaders that have the same query within the same screen (business logic dictates how to filter that data for each view). There's a race condition that happens when data arrives from the server and gets inserted into the database. Here's a scenario when that happens:
1) Data is requested 2) Cursors are initialized and begin the process of querying the ContentResolver for data 3) Data is inserted into db and cursor is notified 4) Since queries for ComposedCursorLoaders happen on the background thread, but the cursor is registered to receive notifications happen on the UI thread, there's a window of opportunity for missed notifications, which is what I saw in my application.
The following is the refactored ComposedCursorLoader which fixes this race condition. The solution is to move the observer registration into the background thread and register the Cursor as soon as it is acquired from the ContentResolver.