Add the Loader and supporting classes.

Loaders are designed to make it easier to manage
asynchronously loading data.

Change-Id: I948db08c721411e94fca071dc6fb4db2b83ea4d6
This commit is contained in:
Jeff Hamilton
2010-05-15 02:20:31 -05:00
parent 3c19d99042
commit 9911b7f83d
5 changed files with 1121 additions and 0 deletions

View File

@@ -19421,6 +19421,21 @@
<parameter name="options" type="int">
</parameter>
</method>
<method name="setDisplayOptions"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="options" type="int">
</parameter>
<parameter name="mask" type="int">
</parameter>
</method>
<method name="setDividerDrawable"
return="void"
abstract="true"
@@ -27547,6 +27562,109 @@
</parameter>
</method>
</class>
<class name="LoaderManagingFragment"
extends="android.app.Fragment"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.content.Loader.OnLoadCompleteListener">
</implements>
<constructor name="LoaderManagingFragment"
type="android.app.LoaderManagingFragment"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
<method name="getLoader"
return="android.content.Loader&lt;D&gt;"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="id" type="int">
</parameter>
</method>
<method name="onCreateLoader"
return="android.content.Loader&lt;D&gt;"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="protected"
>
<parameter name="id" type="int">
</parameter>
<parameter name="args" type="android.os.Bundle">
</parameter>
</method>
<method name="onInitializeLoaders"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="protected"
>
</method>
<method name="onLoadComplete"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="true"
deprecated="not deprecated"
visibility="public"
>
<parameter name="loader" type="android.content.Loader&lt;D&gt;">
</parameter>
<parameter name="data" type="D">
</parameter>
</method>
<method name="onLoadFinished"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="protected"
>
<parameter name="loader" type="android.content.Loader&lt;D&gt;">
</parameter>
<parameter name="data" type="D">
</parameter>
</method>
<method name="startLoading"
return="android.content.Loader&lt;D&gt;"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="protected"
>
<parameter name="id" type="int">
</parameter>
<parameter name="args" type="android.os.Bundle">
</parameter>
</method>
</class>
<class name="LocalActivityManager"
extends="java.lang.Object"
abstract="false"
@@ -35277,6 +35395,58 @@
</parameter>
</constructor>
</class>
<class name="AsyncTaskLoader"
extends="android.content.Loader"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<constructor name="AsyncTaskLoader"
type="android.content.AsyncTaskLoader"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
</constructor>
<method name="cancelLoad"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="forceLoad"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="loadInBackground"
return="D"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
</class>
<class name="BroadcastReceiver"
extends="java.lang.Object"
abstract="true"
@@ -40673,6 +40843,212 @@
</parameter>
</method>
</class>
<class name="CursorLoader"
extends="android.content.AsyncTaskLoader"
abstract="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<constructor name="CursorLoader"
type="android.content.CursorLoader"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="projection" type="java.lang.String[]">
</parameter>
<parameter name="selection" type="java.lang.String">
</parameter>
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</constructor>
<method name="deliverResult"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="cursor" type="android.database.Cursor">
</parameter>
</method>
<method name="destroy"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getProjection"
return="java.lang.String[]"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getSelection"
return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getSelectionArgs"
return="java.lang.String[]"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getSortOrder"
return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getUri"
return="android.net.Uri"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="loadInBackground"
return="android.database.Cursor"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="setProjection"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="projection" type="java.lang.String[]">
</parameter>
</method>
<method name="setSelection"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="selection" type="java.lang.String">
</parameter>
</method>
<method name="setSelectionArgs"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
</method>
<method name="setSortOrder"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</method>
<method name="setUri"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
</method>
<method name="startLoading"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="stopLoading"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
</class>
<interface name="DialogInterface"
abstract="true"
static="false"
@@ -45639,6 +46015,172 @@
</parameter>
</constructor>
</class>
<class name="Loader"
extends="java.lang.Object"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<constructor name="Loader"
type="android.content.Loader"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
</constructor>
<method name="deliverResult"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="data" type="D">
</parameter>
</method>
<method name="destroy"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="forceLoad"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getContext"
return="android.content.Context"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getId"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="registerListener"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="id" type="int">
</parameter>
<parameter name="listener" type="android.content.Loader.OnLoadCompleteListener&lt;D&gt;">
</parameter>
</method>
<method name="startLoading"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="stopLoading"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="unregisterListener"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="listener" type="android.content.Loader.OnLoadCompleteListener&lt;D&gt;">
</parameter>
</method>
</class>
<class name="Loader.ForceLoadContentObserver"
extends="android.database.ContentObserver"
abstract="false"
static="false"
final="true"
deprecated="not deprecated"
visibility="public"
>
<constructor name="Loader.ForceLoadContentObserver"
type="android.content.Loader.ForceLoadContentObserver"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
</class>
<interface name="Loader.OnLoadCompleteListener"
abstract="true"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<method name="onLoadComplete"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="loader" type="android.content.Loader&lt;D&gt;">
</parameter>
<parameter name="data" type="D">
</parameter>
</method>
</interface>
<class name="MutableContextWrapper"
extends="android.content.ContextWrapper"
abstract="false"

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
import android.content.Loader;
import android.os.Bundle;
import java.util.HashMap;
/**
* A Fragment that has utility methods for managing {@link Loader}s.
*
* @param <D> The type of data returned by the Loader. If you're using multiple Loaders with
* different return types use Object and case the results.
*/
public abstract class LoaderManagingFragment<D> extends Fragment
implements Loader.OnLoadCompleteListener<D> {
private boolean mStarted = false;
static final class LoaderInfo<D> {
public Bundle args;
public Loader<D> loader;
}
private HashMap<Integer, LoaderInfo<D>> mLoaders;
private HashMap<Integer, LoaderInfo<D>> mInactiveLoaders;
/**
* Registers a loader with this activity, registers the callbacks on it, and starts it loading.
* If a loader with the same id has previously been started it will automatically be destroyed
* when the new loader completes it's work. The callback will be delivered before the old loader
* is destroyed.
*/
protected Loader<D> startLoading(int id, Bundle args) {
LoaderInfo<D> info = mLoaders.get(id);
if (info != null) {
// Keep track of the previous instance of this loader so we can destroy
// it when the new one completes.
mInactiveLoaders.put(id, info);
}
info = new LoaderInfo<D>();
info.args = args;
mLoaders.put(id, info);
Loader<D> loader = onCreateLoader(id, args);
info.loader = loader;
if (mStarted) {
// The activity will start all existing loaders in it's onStart(), so only start them
// here if we're past that point of the activitiy's life cycle
loader.registerListener(id, this);
loader.startLoading();
}
return loader;
}
protected abstract Loader<D> onCreateLoader(int id, Bundle args);
protected abstract void onInitializeLoaders();
protected abstract void onLoadFinished(Loader<D> loader, D data);
public final void onLoadComplete(Loader<D> loader, D data) {
// Notify of the new data so the app can switch out the old data before
// we try to destroy it.
onLoadFinished(loader, data);
// Look for an inactive loader and destroy it if found
int id = loader.getId();
LoaderInfo<D> info = mInactiveLoaders.get(id);
if (info != null) {
Loader<D> oldLoader = info.loader;
if (oldLoader != null) {
oldLoader.destroy();
}
mInactiveLoaders.remove(id);
}
}
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
if (mLoaders == null) {
// Look for a passed along loader and create a new one if it's not there
// TODO: uncomment once getLastNonConfigurationInstance method is available
// mLoaders = (HashMap<Integer, LoaderInfo>) getLastNonConfigurationInstance();
if (mLoaders == null) {
mLoaders = new HashMap<Integer, LoaderInfo<D>>();
onInitializeLoaders();
}
}
if (mInactiveLoaders == null) {
mInactiveLoaders = new HashMap<Integer, LoaderInfo<D>>();
}
}
@Override
public void onStart() {
super.onStart();
// Call out to sub classes so they can start their loaders
// Let the existing loaders know that we want to be notified when a load is complete
for (HashMap.Entry<Integer, LoaderInfo<D>> entry : mLoaders.entrySet()) {
LoaderInfo<D> info = entry.getValue();
Loader<D> loader = info.loader;
int id = entry.getKey();
if (loader == null) {
loader = onCreateLoader(id, info.args);
info.loader = loader;
}
loader.registerListener(id, this);
loader.startLoading();
}
mStarted = true;
}
@Override
public void onStop() {
super.onStop();
for (HashMap.Entry<Integer, LoaderInfo<D>> entry : mLoaders.entrySet()) {
LoaderInfo<D> info = entry.getValue();
Loader<D> loader = info.loader;
if (loader == null) {
continue;
}
// Let the loader know we're done with it
loader.unregisterListener(this);
// The loader isn't getting passed along to the next instance so ask it to stop loading
if (!getActivity().isChangingConfigurations()) {
loader.stopLoading();
}
}
mStarted = false;
}
/** TO DO: This needs to be turned into a retained fragment.
@Override
public Object onRetainNonConfigurationInstance() {
// Pass the loader along to the next guy
Object result = mLoaders;
mLoaders = null;
return result;
}
**/
@Override
public void onDestroy() {
super.onDestroy();
if (mLoaders != null) {
for (HashMap.Entry<Integer, LoaderInfo<D>> entry : mLoaders.entrySet()) {
LoaderInfo<D> info = entry.getValue();
Loader<D> loader = info.loader;
if (loader == null) {
continue;
}
loader.destroy();
}
}
}
/**
* @return the Loader with the given id or null if no matching Loader
* is found.
*/
public Loader<D> getLoader(int id) {
LoaderInfo<D> loaderInfo = mLoaders.get(id);
if (loaderInfo != null) {
return mLoaders.get(id).loader;
}
return null;
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content;
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> {
/* Runs on a worker thread */
@Override
protected D doInBackground(Void... params) {
return AsyncTaskLoader.this.loadInBackground();
}
/* Runs on the UI thread */
@Override
protected void onPostExecute(D data) {
AsyncTaskLoader.this.dispatchOnLoadComplete(data);
}
}
LoadTask mTask;
public AsyncTaskLoader(Context context) {
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() {
mTask = new LoadTask();
mTask.execute((Void[]) null);
}
/**
* Attempt to cancel the current load task. See {@link AsyncTask#cancel(boolean)}
* for more info.
*
* @return <tt>false</tt> if the task could not be canceled,
* typically because it has already completed normally, or
* because {@link #startLoading()} hasn't been called, and
* <tt>true</tt> otherwise
*/
public boolean cancelLoad() {
if (mTask != null) {
return mTask.cancel(false);
}
return false;
}
void dispatchOnLoadComplete(D data) {
mTask = null;
deliverResult(data);
}
/**
* Called on a worker thread to perform the actual load. Implementations should not deliver the
* results directly, but should return them from this method and deliver them from
* {@link #onPostExecute()}
*
* @return the result of the load
*/
public abstract D loadInBackground();
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content;
import android.database.Cursor;
import android.net.Uri;
/**
* A loader that queries the {@link ContentResolver} and returns a {@link Cursor}.
*/
public class CursorLoader extends AsyncTaskLoader<Cursor> {
Cursor mCursor;
ForceLoadContentObserver mObserver;
boolean mStopped;
Uri mUri;
String[] mProjection;
String mSelection;
String[] mSelectionArgs;
String mSortOrder;
/* Runs on a worker thread */
@Override
public Cursor loadInBackground() {
Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
mSelectionArgs, mSortOrder);
// Ensure the cursor window is filled
if (cursor != null) {
cursor.getCount();
cursor.registerContentObserver(mObserver);
}
return cursor;
}
/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
if (mStopped) {
// An async query came in while the loader is stopped
cursor.close();
return;
}
mCursor = cursor;
super.deliverResult(cursor);
}
public CursorLoader(Context context, Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
super(context);
mObserver = new ForceLoadContentObserver();
mUri = uri;
mProjection = projection;
mSelection = selection;
mSelectionArgs = selectionArgs;
mSortOrder = sortOrder;
}
/**
* 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.
*
* Must be called from the UI thread
*/
@Override
public void startLoading() {
mStopped = false;
if (mCursor != null) {
deliverResult(mCursor);
} else {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
@Override
public void stopLoading() {
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
mCursor = null;
}
// 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 destroy() {
// Ensure the loader is stopped
stopLoading();
}
public Uri getUri() {
return mUri;
}
public void setUri(Uri uri) {
mUri = uri;
}
public String[] getProjection() {
return mProjection;
}
public void setProjection(String[] projection) {
mProjection = projection;
}
public String getSelection() {
return mSelection;
}
public void setSelection(String selection) {
mSelection = selection;
}
public String[] getSelectionArgs() {
return mSelectionArgs;
}
public void setSelectionArgs(String[] selectionArgs) {
mSelectionArgs = selectionArgs;
}
public String getSortOrder() {
return mSortOrder;
}
public void setSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content;
import android.database.ContentObserver;
import android.os.Handler;
/**
* 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.
*
* @param <D> The result returned when the load is complete
*/
public abstract class Loader<D> {
int mId;
OnLoadCompleteListener<D> mListener;
Context mContext;
public final class ForceLoadContentObserver extends ContentObserver {
public ForceLoadContentObserver() {
super(new Handler());
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
@Override
public void onChange(boolean selfChange) {
forceLoad();
}
}
public interface OnLoadCompleteListener<D> {
/**
* Called on the thread that created the Loader when the load is complete.
*
* @param loader the loader that completed the load
* @param data the result of the load
*/
public void onLoadComplete(Loader<D> loader, D data);
}
/**
* Stores away the application context associated with context. Since Loaders can be used
* across multiple activities it's dangerous to store the context directly.
*
* @param context used to retrieve the application context.
*/
public Loader(Context context) {
mContext = context.getApplicationContext();
}
/**
* Sends the result of the load to the registered listener. Should only be called by subclasses.
*
* Must be called from the UI thread.
*
* @param data the result of the load
*/
public void deliverResult(D data) {
if (mListener != null) {
mListener.onLoadComplete(this, data);
}
}
/**
* @return an application context retrieved from the Context passed to the constructor.
*/
public Context getContext() {
return mContext;
}
/**
* @return the ID of this loader
*/
public int getId() {
return mId;
}
/**
* Registers a class that will receive callbacks when a load is complete. The callbacks will
* be called on the UI thread so it's safe to pass the results to widgets.
*
* Must be called from the UI thread
*/
public void registerListener(int id, OnLoadCompleteListener<D> listener) {
if (mListener != null) {
throw new IllegalStateException("There is already a listener registered");
}
mListener = listener;
mId = id;
}
/**
* Must be called from the UI thread
*/
public void unregisterListener(OnLoadCompleteListener<D> listener) {
if (mListener == null) {
throw new IllegalStateException("No listener register");
}
if (mListener != listener) {
throw new IllegalArgumentException("Attempting to unregister the wrong listener");
}
mListener = null;
}
/**
* 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.
*
* Must be called from the UI thread
*/
public abstract void startLoading();
/**
* Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously
* loaded data set and load a new one.
*/
public abstract void forceLoad();
/**
* Stops delivery of updates until the next time {@link #startLoading()} is called
*
* Must be called from the UI thread
*/
public abstract void stopLoading();
/**
* Destroys the loader and frees its resources, making it unusable.
*
* Must be called from the UI thread
*/
public abstract void destroy();
}