summaryrefslogtreecommitdiffstats
path: root/core/java/android/content
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/content')
-rw-r--r--core/java/android/content/AsyncTaskLoader.java6
-rw-r--r--core/java/android/content/CursorLoader.java44
-rw-r--r--core/java/android/content/Loader.java138
3 files changed, 154 insertions, 34 deletions
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index b19c072..30f8ffc 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -53,12 +53,8 @@ public abstract class AsyncTaskLoader<D> extends Loader<D> {
super(context);
}
- /**
- * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously
- * loaded data set and load a new one.
- */
@Override
- public void forceLoad() {
+ protected void onForceLoad() {
cancelLoad();
mTask = new LoadTask();
mTask.execute((Void[]) null);
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 9e03c25..91dd23b 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -20,21 +20,25 @@ import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
/**
* A loader that queries the {@link ContentResolver} and returns a {@link Cursor}.
*/
public class CursorLoader extends AsyncTaskLoader<Cursor> {
- Cursor mCursor;
- ForceLoadContentObserver mObserver;
- boolean mStopped;
- boolean mContentChanged;
- boolean mReset;
+ final ForceLoadContentObserver mObserver;
+
Uri mUri;
String[] mProjection;
String mSelection;
String[] mSelectionArgs;
String mSortOrder;
+ Cursor mCursor;
+ boolean mContentChanged;
+
/* Runs on a worker thread */
@Override
public Cursor loadInBackground() {
@@ -69,7 +73,7 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
Cursor oldCursor = mCursor;
mCursor = cursor;
- if (!mStopped) {
+ if (isStarted()) {
super.deliverResult(cursor);
}
@@ -97,10 +101,7 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
* Must be called from the UI thread
*/
@Override
- public void startLoading() {
- mStopped = false;
- mReset = false;
-
+ protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
@@ -114,17 +115,14 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
* Must be called from the UI thread
*/
@Override
- public void stopLoading() {
+ protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
-
- // Make sure that any outstanding loads clean themselves up properly
- mStopped = true;
}
@Override
public void onContentChanged() {
- if (mStopped) {
+ if (!isStarted()) {
// This loader has been stopped, so we don't want to load
// new data right now... but keep track of it changing to
// refresh later if we start again.
@@ -142,7 +140,7 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
}
@Override
- public void reset() {
+ protected void onReset() {
mReset = true;
// Ensure the loader is stopped
@@ -193,4 +191,18 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
public void setSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ super.dump(prefix, fd, writer, args);
+ writer.print(prefix); writer.print("mUri="); writer.println(mUri);
+ writer.print(prefix); writer.print("mProjection=");
+ writer.println(Arrays.toString(mProjection));
+ writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
+ writer.print(prefix); writer.print("mSelectionArgs=");
+ writer.println(Arrays.toString(mSelectionArgs));
+ writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
+ writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
+ writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged);
+ }
}
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 73d7103..f425b29 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -18,18 +18,27 @@ package android.content;
import android.database.ContentObserver;
import android.os.Handler;
+import android.util.DebugUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
/**
* An abstract class that performs asynchronous loading of data. While Loaders are active
* they should monitor the source of their data and deliver new results when the contents
* change.
*
+ * <p>Subclasses generally must implement at least {@link #onStartLoading()},
+ * {@link #onStopLoading()}, {@link #onForceLoad()}, and {@link #onReset()}.
+ *
* @param <D> The result returned when the load is complete
*/
-public abstract class Loader<D> {
+public class Loader<D> {
int mId;
OnLoadCompleteListener<D> mListener;
Context mContext;
+ boolean mStarted = false;
+ boolean mReset = true;
public final class ForceLoadContentObserver extends ContentObserver {
public ForceLoadContentObserver() {
@@ -122,28 +131,88 @@ public abstract class Loader<D> {
}
/**
+ * Return whether this load has been started. That is, its {@link #startLoading()}
+ * has been called and no calls to {@link #stopLoading()} or
+ * {@link #reset()} have yet been made.
+ */
+ public boolean isStarted() {
+ return mStarted;
+ }
+
+ /**
+ * Return whether this load has been reset. That is, either the loader
+ * has not yet been started for the first time, or its {@link #reset()}
+ * has been called.
+ */
+ public boolean isReset() {
+ return mReset;
+ }
+
+ /**
* 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 loader will monitor the source of
* the data set and may deliver future callbacks if the source changes. Calling
* {@link #stopLoading} will stop the delivery of callbacks.
*
- * <p>Must be called from the UI thread
+ * <p>This updates the Loader's internal state so that
+ * {@link #isStarted()} and {@link #isReset()} will return the correct
+ * values, and then calls the implementation's {@link #onStartLoading()}.
+ *
+ * <p>Must be called from the UI thread.
+ */
+ public void startLoading() {
+ mStarted = true;
+ mReset = false;
+ onStartLoading();
+ }
+
+ /**
+ * Subclasses must implement this to take care of loading their data,
+ * as per {@link #startLoading()}. This is not called by clients directly,
+ * but as a result of a call to {@link #startLoading()}.
*/
- public abstract void startLoading();
+ protected void onStartLoading() {
+ }
/**
* Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously
- * loaded data set and load a new one.
+ * loaded data set and load a new one. This simply calls through to the
+ * implementation's {@link #onForceLoad()}.
+ *
+ * <p>Must be called from the UI thread.
*/
- public abstract void forceLoad();
+ public void forceLoad() {
+ onForceLoad();
+ }
/**
- * Stops delivery of updates until the next time {@link #startLoading()} is called
+ * Subclasses must implement this to take care of requests to {@link #forceLoad()}.
+ */
+ protected void onForceLoad() {
+ }
+
+ /**
+ * Stops delivery of updates until the next time {@link #startLoading()} is called.
*
- * <p>Must be called from the UI thread
+ * <p>This updates the Loader's internal state so that
+ * {@link #isStarted()} will return the correct
+ * value, and then calls the implementation's {@link #onStopLoading()}.
+ *
+ * <p>Must be called from the UI thread.
*/
- public abstract void stopLoading();
+ public void stopLoading() {
+ mStarted = false;
+ onStopLoading();
+ }
+
+ /**
+ * Subclasses must implement this to take care of stopping their loader,
+ * as per {@link #stopLoading()}. This is not called by clients directly,
+ * but as a result of a call to {@link #stopLoading()}.
+ */
+ protected void onStopLoading() {
+ }
/**
* Resets the state of the Loader. The Loader should at this point free
@@ -151,17 +220,24 @@ public abstract class Loader<D> {
* {@link #startLoading()} may later be called at which point it must be
* able to start running again.
*
- * <p>Must be called from the UI thread
+ * <p>This updates the Loader's internal state so that
+ * {@link #isStarted()} and {@link #isReset()} will return the correct
+ * values, and then calls the implementation's {@link #onReset()}.
+ *
+ * <p>Must be called from the UI thread.
*/
public void reset() {
- destroy();
+ onReset();
+ mReset = true;
+ mStarted = false;
}
/**
- * @deprecated Old API, implement reset() now.
+ * Subclasses must implement this to take care of resetting their loader,
+ * as per {@link #reset()}. This is not called by clients directly,
+ * but as a result of a call to {@link #reset()}.
*/
- @Deprecated
- public void destroy() {
+ protected void onReset() {
}
/**
@@ -173,4 +249,40 @@ public abstract class Loader<D> {
public void onContentChanged() {
forceLoad();
}
+
+ /**
+ * For debugging, converts an instance of the Loader's data class to
+ * a string that can be printed. Must handle a null data.
+ */
+ public String dataToString(D data) {
+ StringBuilder sb = new StringBuilder(64);
+ DebugUtils.buildShortClassTag(data, sb);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(64);
+ DebugUtils.buildShortClassTag(this, sb);
+ sb.append(" id=");
+ sb.append(mId);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Print the Loader's state into the given stream.
+ *
+ * @param prefix Text to print at the front of each line.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer A PrintWriter to which the dump is to be set.
+ * @param args Additional arguments to the dump request.
+ */
+ 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(" mReset="); writer.println(mReset);
+ }
} \ No newline at end of file