It's a good practice to cache loaded result to avoid multiple loading of same data.
To invalidate cache onContentChanged()
should be called. If loader has been already started, forceLoad()
will be called, otherwise (if loader in stopped state) loader will be able to understand content change with takeContentChanged()
check.
Remark: onContentChanged()
must be called from the process's main thread.
Javadocs says about takeContentChanged():
Take the current flag indicating whether the loader's content had changed while it was stopped. If it had, true is returned and the flag is cleared.
public abstract class BaseLoader<T> extends AsyncTaskLoader<T> {
// Cached result saved here
private final AtomicReference<T> cache = new AtomicReference<>();
public BaseLoader(@NonNull final Context context) {
super(context);
}
@Override
public final void deliverResult(final T data) {
if (!isReset()) {
// Save loaded result
cache.set(data);
if (isStarted()) {
super.deliverResult(data);
}
}
}
@Override
protected final void onStartLoading() {
// Register observers
registerObserver();
final T cached = cache.get();
// Start new loading if content changed in background
// or if we never loaded any data
if (takeContentChanged() || cached == null) {
forceLoad();
} else {
deliverResult(cached);
}
}
@Override
public final void onStopLoading() {
cancelLoad();
}
@Override
protected final void onReset() {
super.onReset();
onStopLoading();
// Clear cache and remove observers
cache.set(null);
unregisterObserver();
}
/* virtual */
protected void registerObserver() {
// Register observers here, call onContentChanged() to invalidate cache
}
/* virtual */
protected void unregisterObserver() {
// Remove observers
}
}