Fix a bug where we could lose a loader content change.
If AsyncTaskLoader starts a background update due to a content change, and that update is cancelled, we drop the data when it finally arrives and forget that the content changed. If we later come back to the loader, we then end up showing stale data because we don't know that we still need to update due to the old content change. This change adds a couple new APIs to Loader to deal with the time between when you ask for whether there is a content change and finally either commit the data or cancel the update. AsyncTaskLoader is changed to make use of this so that it doesn't lose changes. Change-Id: I3866236b1c22bb9138f2d9f6032b126aeaee2e6e
This commit is contained in:
@@ -6159,6 +6159,7 @@ package android.content {
|
||||
ctor public Loader(android.content.Context);
|
||||
method public void abandon();
|
||||
method public boolean cancelLoad();
|
||||
method public void commitContentChanged();
|
||||
method public java.lang.String dataToString(D);
|
||||
method public void deliverCancellation();
|
||||
method public void deliverResult(D);
|
||||
@@ -6179,6 +6180,7 @@ package android.content {
|
||||
method public void registerListener(int, android.content.Loader.OnLoadCompleteListener<D>);
|
||||
method public void registerOnLoadCanceledListener(android.content.Loader.OnLoadCanceledListener<D>);
|
||||
method public void reset();
|
||||
method public void rollbackContentChanged();
|
||||
method public final void startLoading();
|
||||
method public void stopLoading();
|
||||
method public boolean takeContentChanged();
|
||||
|
||||
@@ -231,6 +231,7 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
|
||||
onCanceled(data);
|
||||
if (mCancellingTask == task) {
|
||||
if (DEBUG) Slog.v(TAG, "Cancelled task is now canceled!");
|
||||
rollbackContentChanged();
|
||||
mLastLoadCompleteTime = SystemClock.uptimeMillis();
|
||||
mCancellingTask = null;
|
||||
if (DEBUG) Slog.v(TAG, "Delivering cancellation");
|
||||
@@ -248,6 +249,7 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
|
||||
// This cursor has been abandoned; just cancel the new data.
|
||||
onCanceled(data);
|
||||
} else {
|
||||
commitContentChanged();
|
||||
mLastLoadCompleteTime = SystemClock.uptimeMillis();
|
||||
mTask = null;
|
||||
if (DEBUG) Slog.v(TAG, "Delivering result");
|
||||
|
||||
@@ -58,6 +58,7 @@ public class Loader<D> {
|
||||
boolean mAbandoned = false;
|
||||
boolean mReset = true;
|
||||
boolean mContentChanged = false;
|
||||
boolean mProcessingChange = false;
|
||||
|
||||
/**
|
||||
* An implementation of a ContentObserver that takes care of connecting
|
||||
@@ -439,6 +440,7 @@ public class Loader<D> {
|
||||
mStarted = false;
|
||||
mAbandoned = false;
|
||||
mContentChanged = false;
|
||||
mProcessingChange = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -458,9 +460,34 @@ public class Loader<D> {
|
||||
public boolean takeContentChanged() {
|
||||
boolean res = mContentChanged;
|
||||
mContentChanged = false;
|
||||
mProcessingChange |= res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commit that you have actually fully processed a content change that
|
||||
* was returned by {@link #takeContentChanged}. This is for use with
|
||||
* {@link #rollbackContentChanged()} to handle situations where a load
|
||||
* is cancelled. Call this when you have completely processed a load
|
||||
* without it being cancelled.
|
||||
*/
|
||||
public void commitContentChanged() {
|
||||
mProcessingChange = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report that you have abandoned the processing of a content change that
|
||||
* was returned by {@link #takeContentChanged()} and would like to rollback
|
||||
* to the state where there is again a pending content change. This is
|
||||
* to handle the case where a data load due to a content change has been
|
||||
* canceled before its data was delivered back to the loader.
|
||||
*/
|
||||
public void rollbackContentChanged() {
|
||||
if (mProcessingChange) {
|
||||
mContentChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when {@link ForceLoadContentObserver} detects a change. The
|
||||
* default implementation checks to see if the loader is currently started;
|
||||
@@ -512,9 +539,14 @@ public class Loader<D> {
|
||||
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
writer.print(prefix); writer.print("mId="); writer.print(mId);
|
||||
writer.print(" mListener="); writer.println(mListener);
|
||||
writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
|
||||
writer.print(" mContentChanged="); writer.print(mContentChanged);
|
||||
writer.print(" mAbandoned="); writer.print(mAbandoned);
|
||||
writer.print(" mReset="); writer.println(mReset);
|
||||
if (mStarted || mContentChanged || mProcessingChange) {
|
||||
writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
|
||||
writer.print(" mContentChanged="); writer.print(mContentChanged);
|
||||
writer.print(" mProcessingChange="); writer.println(mProcessingChange);
|
||||
}
|
||||
if (mAbandoned || mReset) {
|
||||
writer.print(prefix); writer.print("mAbandoned="); writer.print(mAbandoned);
|
||||
writer.print(" mReset="); writer.println(mReset);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user