Last active
July 28, 2024 11:13
-
-
Save HenokT/7873979 to your computer and use it in GitHub Desktop.
An example of a Generic AsyncTaskLoader for Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.yourcompany.util; | |
import android.content.Context; | |
import android.support.v4.content.AsyncTaskLoader; | |
import android.util.Log; | |
import com.yourcompany.util.GenericAsyncTaskLoader.ServiceData; | |
/** | |
* A generic Loader that delegates its actual loading operation to a | |
* CustomLoaderCallbacks<T> instance passed through the constructor. | |
*/ | |
public class GenericAsyncTaskLoader<T extends ServiceData> extends | |
AsyncTaskLoader<T> { | |
private static final String LOG_TAG = "GenericAsyncTaskLoader"; | |
public static class ServiceData { | |
private Exception exception; | |
public ServiceData(Exception ex) { | |
this.exception = ex; | |
} | |
public boolean hasException() { | |
return exception != null; | |
} | |
} | |
public interface ExtendedLoaderCallbacks<T> { | |
public T onLoadInBackground(); | |
public T onExceptionInBackground(Exception ex); | |
public void onLoadCanceled(); | |
} | |
ExtendedLoaderCallbacks<T> mExtendeCallbacks; | |
T mData; | |
/** | |
* ServiceDataLoader expects a reference to an ExtendedLoaderCallbacks | |
* implementation for handling | |
* onLoadInBackground(),onExceptionInBackground() and onLoadCanceled() | |
* events | |
* | |
* @param context | |
* @param extendedCallbacks | |
*/ | |
public ServiceDataLoader(Context context, | |
ExtendedLoaderCallbacks<T> extendedCallbacks) { | |
super(context); | |
mExtendeCallbacks = extendedCallbacks; | |
} | |
/** | |
* This is where the bulk of our work is done. This function is called in a | |
* background thread and should generate a new set of data to be published | |
* by the loader. | |
*/ | |
@Override | |
public T loadInBackground() { | |
Log.d(LOG_TAG, "loadInBackground()"); | |
// Retrieve data | |
T data = null; | |
try { | |
data = mExtendeCallbacks.onLoadInBackground(); | |
} catch (Exception e) { | |
Log.e(LOG_TAG, "An error occurred wile loading data", e); | |
data = mExtendeCallbacks.onExceptionInBackground(e); | |
} | |
// Done! | |
return data; | |
} | |
/** | |
* Called when there is new data to deliver to the client. The super class | |
* will take care of delivering it; the implementation here just adds a | |
* little more logic. | |
*/ | |
@Override | |
public void deliverResult(T data) { | |
Log.d(LOG_TAG, "deliverResult()"); | |
if (isReset()) { | |
// An async query came in while the loader is stopped. We | |
// don't need the result. | |
if (data != null) { | |
onReleaseResources(data); | |
} | |
} | |
T oldData = data; | |
mData = data; | |
if (isStarted()) { | |
// If the Loader is currently started, we can immediately | |
// deliver its results. | |
super.deliverResult(data); | |
} | |
// At this point we can release the resources associated with | |
// 'oldData' if needed; now that the new result is delivered we | |
// know that it is no longer in use. | |
if (oldData != null) { | |
onReleaseResources(oldData); | |
} | |
} | |
/** | |
* Handles a request to start the Loader. | |
*/ | |
@Override | |
protected void onStartLoading() { | |
Log.d(LOG_TAG, "onStartLoading()"); | |
if (mData != null) { | |
// If we currently have a result available, deliver it | |
// immediately. | |
deliverResult(mData); | |
} | |
if (takeContentChanged() || mData == null) { | |
// If the data has changed since the last time it was loaded | |
// or is not currently available, start a load. | |
forceLoad(); | |
} | |
} | |
/** | |
* Handles a request to stop the Loader. | |
*/ | |
@Override | |
protected void onStopLoading() { | |
super.onStopLoading(); | |
Log.d(LOG_TAG, "onStopLoading()"); | |
// Attempt to cancel the current load task if possible. | |
cancelLoad(); | |
} | |
/** | |
* Handles a request to cancel a load. | |
*/ | |
@Override | |
public void onCanceled(T data) { | |
super.onCanceled(data); | |
Log.d(LOG_TAG, "onCanceled()"); | |
mExtendeCallbacks.onLoadCanceled(); | |
// At this point we can release the resources associated with 'apps' | |
// if needed. | |
onReleaseResources(data); | |
} | |
/** | |
* Handles a request to completely reset the Loader. | |
*/ | |
@Override | |
protected void onReset() { | |
super.onReset(); | |
Log.d(LOG_TAG, "onReset()"); | |
// Ensure the loader is stopped | |
onStopLoading(); | |
// At this point we can release the resources associated with 'apps' | |
// if needed. | |
if (mData != null) { | |
onReleaseResources(mData); | |
mData = null; | |
} | |
} | |
/** | |
* Helper function to take care of releasing resources associated with an | |
* actively loaded data set. | |
*/ | |
protected void onReleaseResources(T data) { | |
// For a simple List<> there is nothing to do. For something | |
// like a Cursor, we would close it here. | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An implementation of LoaderManager.LoaderCallbacks and | |
GenericAsyncTaskLoader.ExtendedCallbacks | |
* | |
*/ | |
private class HomeScreenDataLoaderCallbacks implements | |
LoaderManager.LoaderCallbacks<HomeScreenData>, | |
ExtendedLoaderCallbacks<HomeScreenData> { | |
private Application mApplication = getApplication(); | |
@Override | |
public Loader<HomeScreenData> onCreateLoader(int id, Bundle args) { | |
return new GenericAsyncTaskLoader<HomeScreenData>(mApplication, this); | |
} | |
@Override | |
public HomeScreenData onLoadInBackground() { | |
ServiceHelper helper = new ServiceHelper(mApplication); | |
return new HomeScreenData(helper.getHomeScreenStories(), helper.getWeatherCurrent(), | |
helper.getHomeScreenAds()); | |
} | |
@Override | |
public HomeScreenData onExceptionInBackground(Exception ex) { | |
return new HomeScreenData(ex); | |
} | |
@Override | |
public void onLoadCanceled() { | |
dismissProgressDialog(); | |
} | |
@Override | |
public void onLoadFinished(Loader<HomeScreenData> loader, | |
HomeScreenData data) { | |
if (data == null || data.hasException()) { | |
showDataLoadFailureDialog(); | |
return; | |
} | |
mData = data; | |
if (isViewCreated()) { | |
updateViews(); | |
} | |
dismissProgressDialog(); | |
} | |
@Override | |
public void onLoaderReset(Loader<HomeScreenData> loader) { | |
dismissProgressDialog(); | |
mData = null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Override | |
public void onActivityCreated(Bundle savedInstanceState) { | |
super.onActivityCreated(savedInstanceState); | |
if (mData == null) { | |
showProgressDialog(); | |
} | |
// Prepare the loader. Either re-connect with an existing one, | |
// or start a new one. | |
getLoaderManager().initLoader(MAIN_DATA_LOADER_ID, null, | |
new DataLoaderCallbacks()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment