Loading docs/html/training/load-data-background/handle-results.jd 0 → 100644 +137 −0 Original line number Diff line number Diff line page.title=Handling the Results trainingnavtop=true startpage=true @jd:body <!-- This is the training bar --> <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li> <a href="#HandleResults">Handle Query Results</a> </li> <li> <a href="#HandleReset">Delete Old Cursor References</a></li> </ol> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> As shown in the previous lesson, you should begin loading your data with a {@link android.support.v4.content.CursorLoader} in your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. The loader then provides the query results to your {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} in your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished LoaderCallbacks.onLoadFinished()}. One of the incoming arguments to this method is a {@link android.database.Cursor} containing the query results. You can use this object to update your data display or do further processing. </p> <p> Besides {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} and {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, you also have to implement {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. This method is invoked when {@link android.support.v4.content.CursorLoader} detects that data associated with the {@link android.database.Cursor} has changed. When the data changes, the framework also re-runs the current query. </p> <h2 id="HandleResults">Handle Query Results</h2> <p> To display {@link android.database.Cursor} data returned by {@link android.support.v4.content.CursorLoader}, use a {@link android.view.View} class that implements {@link android.widget.AdapterView} and provide the view with an adapter that implements {@link android.support.v4.widget.CursorAdapter}. The system then automatically moves data from the {@link android.database.Cursor} to the view. </p> <p> You can set up the linkage between the view and adapter before you have any data to display, and then move a {@link android.database.Cursor} into the adapter in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} method. As soon as you move the {@link android.database.Cursor} into the adapter, the system automatically updates the view. This also happens if you change the contents of the {@link android.database.Cursor}. </p> <p> For example: </p> <pre> public String[] mFromColumns = { DataProviderContract.IMAGE_PICTURENAME_COLUMN }; public int[] mToFields = { R.id.PictureName }; // Gets a handle to a List View ListView mListView = (ListView) findViewById(R.id.dataList); /* * Defines a SimpleCursorAdapter for the ListView * */ SimpleCursorAdapter mAdapter = new SimpleCursorAdapter( this, // Current context R.layout.list_item, // Layout for a single row null, // No Cursor yet mFromColumns, // Cursor columns to use mToFields, // Layout fields to use 0 // No flags ); // Sets the adapter for the view mListView.setAdapter(mAdapter); ... /* * Defines the callback that {@link android.support.v4.content.CursorLoader} calls * when it's finished its query */ @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { ... /* * Moves the query results into the adapter, causing the * ListView fronting this adapter to re-display */ mAdapter.changeCursor(cursor); } </pre> <h2 id="HandleReset">Delete Old Cursor References</h2> <p> The {@link android.support.v4.content.CursorLoader} is reset whenever its {@link android.database.Cursor} becomes invalid. This usually occurs because the data associated with the {@link android.database.Cursor} has changed. Before re-running the query, the framework calls your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. In this callback, you should delete all references to the current {@link android.database.Cursor} in order to prevent memory leaks. Once {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} finishes, {@link android.support.v4.content.CursorLoader} re-runs its query. </p> <p> For example: </p> <pre> /* * Invoked when the CursorLoader is being reset. For example, this is * called if the data in the provider changes and the Cursor becomes stale. */ @Override public void onLoaderReset(Loader<Cursor> loader) { /* * Clears out the adapter's reference to the Cursor. * This prevents memory leaks. */ mAdapter.changeCursor(null); } </pre> docs/html/training/load-data-background/index.jd 0 → 100644 +77 −0 Original line number Diff line number Diff line page.title=Loading Data in the Background trainingnavtop=true startpage=true @jd:body <div id="tb-wrapper"> <div id="tb"> <!-- Required platform, tools, add-ons, devices, knowledge, etc. --> <h2>Dependencies and prerequisites</h2> <ul> <li> Android 1.6 or later </li> </ul> <!-- related docs (NOT javadocs) --> <h2>You should also read</h2> <ul> <li> <a href="{@docRoot}guide/components/loaders.html">Loaders</a> </li> <li> <a href="{@docRoot}guide/topics/data/data-storage.html#db">Using Databases</a> </li> <li> <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">Content Provider Basics</a> </li> </ul> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> Querying a {@link android.content.ContentProvider} for data you want to display takes time. If you run the query directly from an {@link android.app.Activity}, it may get blocked and cause the system to issue an "Application Not Responding" message. Even if it doesn't, users will see an annoying delay in the UI. To avoid these problems, you should initiate a query on a separate thread, wait for it to finish, and then display the results. </p> <p> You can do this in a straightforward way by using an object that runs a query asynchronously in the background and reconnects to your {@link android.app.Activity} when it's finished. This object is a {@link android.support.v4.content.CursorLoader}. Besides doing the initial background query, a {@link android.support.v4.content.CursorLoader} automatically re-runs the query when data associated with the query changes. </p> <p> This class describes how to use a {@link android.support.v4.content.CursorLoader} to run a background query. Examples in this class use the {@link android.support.v4 v4 support library} versions of classes, which support platforms starting with Android 1.6. </p> <h2>Lessons</h2> <dl> <dt> <strong><a href="setup-loader.html">Running a Query with a CursorLoader</a></strong> </dt> <dd> Learn how to run a query in the background, using a {@link android.support.v4.content.CursorLoader}. </dd> <dt> <strong> <a href="handle-results.html">Handling the Results</a> </strong> </dt> <dd> Learn how to handle the {@link android.database.Cursor} returned from the query, and how to remove references to the current {@link android.database.Cursor} when the loader framework re-sets the {@link android.support.v4.content.CursorLoader}. </dd> </dl> docs/html/training/load-data-background/setup-loader.jd 0 → 100644 +142 −0 Original line number Diff line number Diff line page.title=Running a Query with a CursorLoader trainingnavtop=true startpage=true @jd:body <!-- This is the training bar --> <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li> <a href="#Extend">Define an Activity That Uses CursorLoader</a> </li> <li> <a href="#InitializeLoader">Initialize the Query</a> </li> <li> <a href="#DefineLaunch">Start the Query</a> </li> </ol> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> A {@link android.support.v4.content.CursorLoader} runs an asynchronous query in the background against a {@link android.content.ContentProvider}, and returns the results to the {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} from which it was called. This allows the {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} to continue to interact with the user while the query is ongoing. </p> <h2 id="Extend">Define an Activity That Uses CursorLoader</h2> <p> To use a {@link android.support.v4.content.CursorLoader} with an {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity}, use the {@link android.support.v4.app.LoaderManager.LoaderCallbacks LoaderCallbacks<Cursor>} interface. A {@link android.support.v4.content.CursorLoader} invokes callbacks defined in this interface to communicate with the class; this lesson and the next one describe each callback in detail. </p> <p> For example, this is how you should define a {@link android.support.v4.app.FragmentActivity} that uses the support library version of {@link android.support.v4.content.CursorLoader}. By extending {@link android.support.v4.app.FragmentActivity}, you get support for {@link android.support.v4.content.CursorLoader} as well as {@link android.support.v4.app.Fragment}: </p> <pre> public class PhotoThumbnailFragment extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> { ... } </pre> <h2 id="InitializeLoader">Initialize the Query</h2> <p> To initialize a query, call {@link android.support.v4.app.LoaderManager#initLoader LoaderManager.initLoader()}. This initializes the background framework. You can do this after the user has entered data that's used in the query, or, if you don't need any user data, you can do it in {@link android.support.v4.app.FragmentActivity#onCreate onCreate()} or {@link android.support.v4.app.Fragment#onCreateView onCreateView()}. For example: </p> <pre> // Identifies a particular Loader being used in this component private static final int URL_LOADER = 0; ... /* When the system is ready for the Fragment to appear, this displays * the Fragment's View */ public View onCreateView( LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) { ... /* * Initializes the CursorLoader. The URL_LOADER value is eventually passed * to onCreateLoader(). */ getLoaderManager().initLoader(URL_LOADER, null, this); ... } </pre> <p class="note"> <strong>Note:</strong> The method {@link android.support.v4.app.Fragment#getLoaderManager getLoaderManager()} is only available in the {@link android.support.v4.app.Fragment} class. To get a {@link android.support.v4.app.LoaderManager} in a {@link android.support.v4.app.FragmentActivity}, call {@link android.support.v4.app.FragmentActivity#getSupportLoaderManager getSupportLoaderManager()}. </p> <h2 id="DefineLaunch">Start the Query</h2> <p> As soon as the background framework is initialized, it calls your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. To start the query, return a {@link android.support.v4.content.CursorLoader} from this method. You can instantiate an empty {@link android.support.v4.content.CursorLoader} and then use its methods to define your query, or you can instantiate the object and define the query at the same time: </p> <pre> /* * Callback that's invoked when the system has initialized the Loader and * is ready to start the query. This usually happens when initLoader() is * called. The loaderID argument contains the ID value passed to the * initLoader() call. */ @Override public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) { /* * Takes action based on the ID of the Loader that's being created */ switch (loaderID) { case URL_LOADER: // Returns a new CursorLoader return new CursorLoader( getActivity(), // Parent activity context mDataUrl, // Table to query mProjection, // Projection to return null, // No selection clause null, // No selection arguments null // Default sort order ); default: // An invalid id was passed in return null; } } </pre> <p> Once the background framework has the object, it starts the query in the background. When the query is done, the background framework calls {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, which is described in the next lesson. </p> docs/html/training/training_toc.cs +0 −3 Original line number Diff line number Diff line Loading @@ -1028,8 +1028,6 @@ </li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"> <a href="<?cs var:toroot ?>training/monetization/index.html" Loading @@ -1050,7 +1048,6 @@ <!-- End best Publishing --> </ul><!-- nav --> <script type="text/javascript"> <!-- buildToggleLists(); Loading Loading
docs/html/training/load-data-background/handle-results.jd 0 → 100644 +137 −0 Original line number Diff line number Diff line page.title=Handling the Results trainingnavtop=true startpage=true @jd:body <!-- This is the training bar --> <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li> <a href="#HandleResults">Handle Query Results</a> </li> <li> <a href="#HandleReset">Delete Old Cursor References</a></li> </ol> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> As shown in the previous lesson, you should begin loading your data with a {@link android.support.v4.content.CursorLoader} in your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. The loader then provides the query results to your {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} in your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished LoaderCallbacks.onLoadFinished()}. One of the incoming arguments to this method is a {@link android.database.Cursor} containing the query results. You can use this object to update your data display or do further processing. </p> <p> Besides {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} and {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, you also have to implement {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. This method is invoked when {@link android.support.v4.content.CursorLoader} detects that data associated with the {@link android.database.Cursor} has changed. When the data changes, the framework also re-runs the current query. </p> <h2 id="HandleResults">Handle Query Results</h2> <p> To display {@link android.database.Cursor} data returned by {@link android.support.v4.content.CursorLoader}, use a {@link android.view.View} class that implements {@link android.widget.AdapterView} and provide the view with an adapter that implements {@link android.support.v4.widget.CursorAdapter}. The system then automatically moves data from the {@link android.database.Cursor} to the view. </p> <p> You can set up the linkage between the view and adapter before you have any data to display, and then move a {@link android.database.Cursor} into the adapter in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} method. As soon as you move the {@link android.database.Cursor} into the adapter, the system automatically updates the view. This also happens if you change the contents of the {@link android.database.Cursor}. </p> <p> For example: </p> <pre> public String[] mFromColumns = { DataProviderContract.IMAGE_PICTURENAME_COLUMN }; public int[] mToFields = { R.id.PictureName }; // Gets a handle to a List View ListView mListView = (ListView) findViewById(R.id.dataList); /* * Defines a SimpleCursorAdapter for the ListView * */ SimpleCursorAdapter mAdapter = new SimpleCursorAdapter( this, // Current context R.layout.list_item, // Layout for a single row null, // No Cursor yet mFromColumns, // Cursor columns to use mToFields, // Layout fields to use 0 // No flags ); // Sets the adapter for the view mListView.setAdapter(mAdapter); ... /* * Defines the callback that {@link android.support.v4.content.CursorLoader} calls * when it's finished its query */ @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { ... /* * Moves the query results into the adapter, causing the * ListView fronting this adapter to re-display */ mAdapter.changeCursor(cursor); } </pre> <h2 id="HandleReset">Delete Old Cursor References</h2> <p> The {@link android.support.v4.content.CursorLoader} is reset whenever its {@link android.database.Cursor} becomes invalid. This usually occurs because the data associated with the {@link android.database.Cursor} has changed. Before re-running the query, the framework calls your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. In this callback, you should delete all references to the current {@link android.database.Cursor} in order to prevent memory leaks. Once {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()} finishes, {@link android.support.v4.content.CursorLoader} re-runs its query. </p> <p> For example: </p> <pre> /* * Invoked when the CursorLoader is being reset. For example, this is * called if the data in the provider changes and the Cursor becomes stale. */ @Override public void onLoaderReset(Loader<Cursor> loader) { /* * Clears out the adapter's reference to the Cursor. * This prevents memory leaks. */ mAdapter.changeCursor(null); } </pre>
docs/html/training/load-data-background/index.jd 0 → 100644 +77 −0 Original line number Diff line number Diff line page.title=Loading Data in the Background trainingnavtop=true startpage=true @jd:body <div id="tb-wrapper"> <div id="tb"> <!-- Required platform, tools, add-ons, devices, knowledge, etc. --> <h2>Dependencies and prerequisites</h2> <ul> <li> Android 1.6 or later </li> </ul> <!-- related docs (NOT javadocs) --> <h2>You should also read</h2> <ul> <li> <a href="{@docRoot}guide/components/loaders.html">Loaders</a> </li> <li> <a href="{@docRoot}guide/topics/data/data-storage.html#db">Using Databases</a> </li> <li> <a href="{@docRoot}guide/topics/providers/content-provider-basics.html">Content Provider Basics</a> </li> </ul> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> Querying a {@link android.content.ContentProvider} for data you want to display takes time. If you run the query directly from an {@link android.app.Activity}, it may get blocked and cause the system to issue an "Application Not Responding" message. Even if it doesn't, users will see an annoying delay in the UI. To avoid these problems, you should initiate a query on a separate thread, wait for it to finish, and then display the results. </p> <p> You can do this in a straightforward way by using an object that runs a query asynchronously in the background and reconnects to your {@link android.app.Activity} when it's finished. This object is a {@link android.support.v4.content.CursorLoader}. Besides doing the initial background query, a {@link android.support.v4.content.CursorLoader} automatically re-runs the query when data associated with the query changes. </p> <p> This class describes how to use a {@link android.support.v4.content.CursorLoader} to run a background query. Examples in this class use the {@link android.support.v4 v4 support library} versions of classes, which support platforms starting with Android 1.6. </p> <h2>Lessons</h2> <dl> <dt> <strong><a href="setup-loader.html">Running a Query with a CursorLoader</a></strong> </dt> <dd> Learn how to run a query in the background, using a {@link android.support.v4.content.CursorLoader}. </dd> <dt> <strong> <a href="handle-results.html">Handling the Results</a> </strong> </dt> <dd> Learn how to handle the {@link android.database.Cursor} returned from the query, and how to remove references to the current {@link android.database.Cursor} when the loader framework re-sets the {@link android.support.v4.content.CursorLoader}. </dd> </dl>
docs/html/training/load-data-background/setup-loader.jd 0 → 100644 +142 −0 Original line number Diff line number Diff line page.title=Running a Query with a CursorLoader trainingnavtop=true startpage=true @jd:body <!-- This is the training bar --> <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li> <a href="#Extend">Define an Activity That Uses CursorLoader</a> </li> <li> <a href="#InitializeLoader">Initialize the Query</a> </li> <li> <a href="#DefineLaunch">Start the Query</a> </li> </ol> <h2>Try it out</h2> <div class="download-box"> <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a> <p class="filename">ThreadSample.zip</p> </div> </div> </div> <p> A {@link android.support.v4.content.CursorLoader} runs an asynchronous query in the background against a {@link android.content.ContentProvider}, and returns the results to the {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} from which it was called. This allows the {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity} to continue to interact with the user while the query is ongoing. </p> <h2 id="Extend">Define an Activity That Uses CursorLoader</h2> <p> To use a {@link android.support.v4.content.CursorLoader} with an {@link android.app.Activity} or {@link android.support.v4.app.FragmentActivity}, use the {@link android.support.v4.app.LoaderManager.LoaderCallbacks LoaderCallbacks<Cursor>} interface. A {@link android.support.v4.content.CursorLoader} invokes callbacks defined in this interface to communicate with the class; this lesson and the next one describe each callback in detail. </p> <p> For example, this is how you should define a {@link android.support.v4.app.FragmentActivity} that uses the support library version of {@link android.support.v4.content.CursorLoader}. By extending {@link android.support.v4.app.FragmentActivity}, you get support for {@link android.support.v4.content.CursorLoader} as well as {@link android.support.v4.app.Fragment}: </p> <pre> public class PhotoThumbnailFragment extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> { ... } </pre> <h2 id="InitializeLoader">Initialize the Query</h2> <p> To initialize a query, call {@link android.support.v4.app.LoaderManager#initLoader LoaderManager.initLoader()}. This initializes the background framework. You can do this after the user has entered data that's used in the query, or, if you don't need any user data, you can do it in {@link android.support.v4.app.FragmentActivity#onCreate onCreate()} or {@link android.support.v4.app.Fragment#onCreateView onCreateView()}. For example: </p> <pre> // Identifies a particular Loader being used in this component private static final int URL_LOADER = 0; ... /* When the system is ready for the Fragment to appear, this displays * the Fragment's View */ public View onCreateView( LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) { ... /* * Initializes the CursorLoader. The URL_LOADER value is eventually passed * to onCreateLoader(). */ getLoaderManager().initLoader(URL_LOADER, null, this); ... } </pre> <p class="note"> <strong>Note:</strong> The method {@link android.support.v4.app.Fragment#getLoaderManager getLoaderManager()} is only available in the {@link android.support.v4.app.Fragment} class. To get a {@link android.support.v4.app.LoaderManager} in a {@link android.support.v4.app.FragmentActivity}, call {@link android.support.v4.app.FragmentActivity#getSupportLoaderManager getSupportLoaderManager()}. </p> <h2 id="DefineLaunch">Start the Query</h2> <p> As soon as the background framework is initialized, it calls your implementation of {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. To start the query, return a {@link android.support.v4.content.CursorLoader} from this method. You can instantiate an empty {@link android.support.v4.content.CursorLoader} and then use its methods to define your query, or you can instantiate the object and define the query at the same time: </p> <pre> /* * Callback that's invoked when the system has initialized the Loader and * is ready to start the query. This usually happens when initLoader() is * called. The loaderID argument contains the ID value passed to the * initLoader() call. */ @Override public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) { /* * Takes action based on the ID of the Loader that's being created */ switch (loaderID) { case URL_LOADER: // Returns a new CursorLoader return new CursorLoader( getActivity(), // Parent activity context mDataUrl, // Table to query mProjection, // Projection to return null, // No selection clause null, // No selection arguments null // Default sort order ); default: // An invalid id was passed in return null; } } </pre> <p> Once the background framework has the object, it starts the query in the background. When the query is done, the background framework calls {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()}, which is described in the next lesson. </p>
docs/html/training/training_toc.cs +0 −3 Original line number Diff line number Diff line Loading @@ -1028,8 +1028,6 @@ </li> </ul> </li> <li class="nav-section"> <div class="nav-section-header"> <a href="<?cs var:toroot ?>training/monetization/index.html" Loading @@ -1050,7 +1048,6 @@ <!-- End best Publishing --> </ul><!-- nav --> <script type="text/javascript"> <!-- buildToggleLists(); Loading