Preventing cursor leaks when a query is interrupted

Re-ran runtest cts-os

Change-Id: I518a2a4f842b01d082078e16643aa377a4575237
This commit is contained in:
Dmitri Plotnikov
2010-06-16 15:38:07 -07:00
parent ce718947db
commit bef9c7a59d
3 changed files with 44 additions and 7 deletions

View File

@@ -20,15 +20,19 @@ import android.os.AsyncTask;
/**
* Abstract Loader that provides an {@link AsyncTask} to do the work.
*
*
* @param <D> the data type to be loaded.
*/
public abstract class AsyncTaskLoader<D> extends Loader<D> {
final class LoadTask extends AsyncTask<Void, Void, D> {
private D result;
/* Runs on a worker thread */
@Override
protected D doInBackground(Void... params) {
return AsyncTaskLoader.this.loadInBackground();
result = AsyncTaskLoader.this.loadInBackground();
return result;
}
/* Runs on the UI thread */
@@ -36,6 +40,11 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
protected void onPostExecute(D data) {
AsyncTaskLoader.this.dispatchOnLoadComplete(data);
}
@Override
protected void onCancelled() {
AsyncTaskLoader.this.onCancelled(result);
}
}
LoadTask mTask;
@@ -50,6 +59,7 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
*/
@Override
public void forceLoad() {
cancelLoad();
mTask = new LoadTask();
mTask.execute((Void[]) null);
}
@@ -65,11 +75,20 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
*/
public boolean cancelLoad() {
if (mTask != null) {
return mTask.cancel(false);
boolean cancelled = mTask.cancel(false);
mTask = null;
return cancelled;
}
return false;
}
/**
* Called if the task was canceled before it was completed. Gives the class a chance
* to properly dispose of the result.
*/
public void onCancelled(D data) {
}
void dispatchOnLoadComplete(D data) {
mTask = null;
deliverResult(data);
@@ -78,7 +97,7 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
/**
* Called on a worker thread to perform the actual load. Implementations should not deliver the
* results directly, but should return them from this method, which will eventually end up
* calling deliverResult on the UI thread. If implementations need to process
* calling deliverResult on the UI thread. If implementations need to process
* the results on the UI thread they may override deliverResult and do so
* there.
*

View File

@@ -71,7 +71,7 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
* the result may be passed to the callbacks immediately.
*
* Must be called from the UI thread
*/
@@ -103,6 +103,13 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
mStopped = true;
}
@Override
public void onCancelled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
@Override
public void destroy() {
// Ensure the loader is stopped

View File

@@ -187,6 +187,17 @@ public abstract class AsyncTask<Params, Progress, Result> {
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void set(Result v) {
super.set(v);
if (isCancelled()) {
Message message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
message.sendToTarget();
}
}
@Override
protected void done() {
Message message;
@@ -401,7 +412,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* publish updates on the UI thread while the background computation is
* still running. Each call to this method will trigger the execution of
* {@link #onProgressUpdate} on the UI thread.
*
*
* {@link #onProgressUpdate} will note be called if the task has been
* canceled.
*