Last active
August 29, 2015 14:05
-
-
Save drewhannay/74d0059055d49b3f3029 to your computer and use it in GitHub Desktop.
Extension of Android's AsyncTaskLoader which takes care of the boilerplate details and adds support for loading Broadcasts
This file contains hidden or 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
import android.content.Context; | |
import android.content.Intent; | |
import android.support.v4.content.AsyncTaskLoader; | |
import android.support.v4.content.LocalBroadcastManager; | |
/** | |
* Base class which takes care of the boilerplate details involved in extending | |
* AsyncTaskLoader and adds convenience methods for registering and unregistering | |
* an observer for the Loader | |
* | |
* @param <D> | |
* The type of data loaded by this Loader | |
*/ | |
public abstract class AsyncTaskLoaderBase<D> extends AsyncTaskLoader<D> | |
{ | |
private D mData; | |
public AsyncTaskLoaderBase(Context context) | |
{ | |
super(context); | |
} | |
/** | |
* Get the Intent Action string used to listen to Broadcast intents | |
* sent when the Loader starts working. NOTE: Implementors must return a | |
* string that is unique to their Loader to ensure that only the proper | |
* listeners receive the broadcasts. | |
* | |
* @return A String that is unique to this Loader and action | |
*/ | |
public abstract String getLoadingStartedIntentAction(); | |
/** | |
* Get the Intent Action string used to listen to Broadcast intents | |
* sent when the Loader finishes working. NOTE: Implementors must return a | |
* string that is unique to their Loader to ensure that only the proper | |
* listeners receive the broadcasts. | |
* | |
* @return A String that is unique to this Loader and action | |
*/ | |
public abstract String getLoadingFinishedIntentAction(); | |
@Override | |
public final D loadInBackground() | |
{ | |
Intent intent = new Intent(getLoadingStartedIntentAction()); | |
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent); | |
D data = loadInBackgroundCore(); | |
intent = new Intent(getLoadingFinishedIntentAction()); | |
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent); | |
return data; | |
} | |
public abstract D loadInBackgroundCore(); | |
@Override | |
public void deliverResult(D data) | |
{ | |
// the Loader has been reset; ignore the result and invalidate the data | |
if (isReset()) | |
{ | |
releaseResources(data); | |
return; | |
} | |
// hold a reference to the old data so we can release it after delivering | |
// the new data to the client | |
D oldData = mData; | |
mData = data; | |
// if the Loader is in a started state, deliver the results to the client | |
if (isStarted()) | |
super.deliverResult(data); | |
if (oldData != null && oldData != data) | |
releaseResources(data); | |
} | |
@Override | |
protected void onStartLoading() | |
{ | |
// deliver any previously loaded data immediately | |
if (mData != null) | |
deliverResult(mData); | |
registerObserver(); | |
// if the data has changed since the last time it was loaded | |
// or is not currently available, start a load | |
if (mData == null || takeContentChanged()) | |
forceLoad(); | |
} | |
@Override | |
protected void onStopLoading() | |
{ | |
// attempt to cancel the current load task if possible | |
cancelLoad(); | |
// note that we leave the observer as is. Loaders in a stopped state | |
// should still monitor the data source for changes so that the Loader | |
// will know to force a new load if it is ever started again | |
} | |
@Override | |
protected void onReset() | |
{ | |
// ensure the Loader has been stopped | |
onStopLoading(); | |
// at this point we can release the resources associated with mData | |
if (mData != null) | |
{ | |
releaseResources(mData); | |
mData = null; | |
} | |
// the Loader is being reset, so we should stop monitoring for changes | |
unregisterObserver(); | |
} | |
@Override | |
public void onCanceled(D data) | |
{ | |
// attempt to cancel the current asynchronous load | |
super.onCanceled(data); | |
// the load has been canceled, so we should release the resources | |
// associated with 'data' | |
releaseResources(data); | |
} | |
/** | |
* Implementers should override this method and perform any necessary actions | |
* to release the given data. For a simple List, there is nothing to do. For | |
* something like a Cursor, it should be closed in this method. All resources | |
* associated with the Loader should be released here. | |
* | |
* @param data | |
* The data to be released | |
*/ | |
protected void releaseResources(D data) | |
{ | |
} | |
/** | |
* Called at the appropriate time for registering observers on the content | |
* being loaded. The observer could be anything so long as it is able to | |
* detect content changes and report them to the Loader with a call to | |
* onContentChanged(). For example, if you were writing a Loader which loads a | |
* list of all installed applications on the device, the observer could be a | |
* BroadcastReceiver that listens for the ACTION_PACKAGE_ADDED intent, and | |
* calls onContentChanged() on the particular Loader whenever the receiver | |
* detects that a new application has been installed | |
* NOTE: This method may be called multiple times without a call to | |
* unregisterObserver, so your implementation should be idempotent | |
*/ | |
protected void registerObserver() | |
{ | |
} | |
/** | |
* Called at the appropriate time for unregistering observers on the content | |
* being loaded. | |
*/ | |
protected void unregisterObserver() | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment