Back to project page streaming_project.
The source code is released under:
GNU General Public License
If you think the Android project streaming_project listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.example.streaming.streaming; //ww w . j a va 2 s . c o m import android.content.Context; import android.database.Cursor; import android.support.v4.content.AsyncTaskLoader; // TODO: for all comments at the start of a class declaration, use /**/ instead /* A loader for SQLite cursors. It is a base class and thus it will be sub-classed in MediaListFragment as an inner class. It implements the AsyncTaskLoader API to efficiently load and hold a Cursor in the mCursor instance variable A loader fetches the data without blocking the main thread and delivers the results to whomever is interested. We will use it to pull data for media from the database on a background thread There are three built-in types of loaders: Loader, AsyncTaskLoader, and CursorLoader. See pp.561-562 for descriptions on these types of loaders An AsyncTaskLoader is an abstract Loader that uses an AsyncTask to move the work of loading to another thread. Almost all useful loader classes you create will be sub-classed of AsyncTaskLoader LoaderManager handles all communications with loaders. It is responsible for starting, stopping, and maintaining the lifecycle of any Loaders associated with a component. Call the getLoaderManager() method within a Fragment or Activity to return an implementation to work with. It is one the two abstract subclasses of AsyncTaskLoader that we implemented. The other one is DataLoader<D> which is capable of loading any kind of data and simplifies the use of AsyncTaskLoader for subclasses This loader executes the query of loading the list of media on a separate thread (from the main thread). It is best practice to keep database work off of the main thread as much as possible. The app currently loads two chunks of data: the list of media (a MediaCursor) and an individual Media. Each of these comes from the SQLite database, and should therefore be moved to a Loader to create a smooth user experience. SQLiteCursorLoader is a simplified version of the framework's CursorLoader that will work with a Cursor coming from any source. It is started (and restarted) by the LoaderManager MediaListFragment must implement the LoaderCallbacks interface for a Cursor to know when the data is ready. SQLiteCursorLoader mimics most of the code in CursorLoader, without the requirement of using a ContentProvider (to load a Cursor) because there is no way to use CursorLoader with cursors that come from a SQLiteDatabase (? TODO: check if it is true because com.stylingandroid.adapter seems to use CursorLoader with a ContentProvider that uses Cursors that come from a SQLiteDatabase */ // TODO: understand what is happening here public abstract class SQLiteCursorLoader extends AsyncTaskLoader<Cursor> { private Cursor mCursor; public SQLiteCursorLoader(Context context) { super(context); } protected abstract Cursor loadCursor(); @Override // Calls the abstract loadCursor() method to get the Cursor and calls getCount() method on the // Cursor to ensure that the data is available in memory once it is passed over to the main // thread public Cursor loadInBackground() { Cursor cursor = loadCursor(); if (cursor != null) { // Ensure that the content window is filled cursor.getCount(); } return cursor; } @Override public void deliverResult(Cursor data) { Cursor oldCursor = mCursor; mCursor = data; // Check if the loader is started, i.e. the data can be delivered if (isStarted()) { super.deliverResult(data); } // Check if old cursor is no longer needed if (oldCursor != null && oldCursor != data && !oldCursor.isClosed()) { // Free up the old cursor' resources // NOTE: Because an existing cursor may be cached and redelivered, it is important to // make sure that the old cursor and the new cursor are not the same before the old // cursor is closed. oldCursor.close(); } } // NOTE: the remaining method implementations are not critical to understanding for the purposes // of the Streaming application @Override protected void onStartLoading() { if (mCursor != null) { deliverResult(mCursor); } if (takeContentChanged() || mCursor == null) { forceLoad(); } } @Override protected void onStopLoading() { // Attempt to cancel the current load task if possible. cancelLoad(); } @Override public void onCanceled(Cursor cursor) { if (cursor != null && !cursor.isClosed()) { cursor.close(); } } @Override protected void onReset() { super.onReset(); // Ensure the loader is stopped onStopLoading(); if (mCursor != null && !mCursor.isClosed()) { mCursor.close(); } mCursor = null; } }