diff options
| -rw-r--r-- | docs/html/training/load-data-background/define-launch-query.jd | 83 | ||||
| -rw-r--r-- | docs/html/training/load-data-background/handle-results.jd | 104 | ||||
| -rw-r--r-- | docs/html/training/load-data-background/index.jd | 117 | ||||
| -rw-r--r-- | docs/html/training/load-data-background/setup-loader.jd | 90 | ||||
| -rw-r--r-- | docs/html/training/training_toc.cs | 63 |
5 files changed, 435 insertions, 22 deletions
diff --git a/docs/html/training/load-data-background/define-launch-query.jd b/docs/html/training/load-data-background/define-launch-query.jd new file mode 100644 index 000000000000..f7978f4a8984 --- /dev/null +++ b/docs/html/training/load-data-background/define-launch-query.jd @@ -0,0 +1,83 @@ +page.title=Defining and Launching the Query +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="#DefineLaunch">Define and Launch the Query</a> + </li> +</ol> + </div> +</div> + +<p> + To perform a query, create the {@link android.support.v4.content.CursorLoader}, set up its + query, and pass it to the loader framework. From then on, the framework manages everything. + It runs the query on a background thread, returns the results to the foreground, and + watches for changes to the data associated with the query. +</p> +<p> + Pass a {@link android.support.v4.content.CursorLoader} to the loader framework in + your implementation of + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}. + The loader framework calls this method when you <i>create</i> a loader by calling + {@link android.support.v4.app.LoaderManager#initLoader initLoader()}. You can create + a {@link android.support.v4.content.CursorLoader} anywhere, + but the preferred way is to create it in + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()}, + because this defers creation until the object is actually needed. +</p> +<p> + Notice that {@link android.support.v4.app.LoaderManager#initLoader initLoader()} will only + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader onCreateLoader()} + if the {@link android.support.v4.content.CursorLoader} doesn't already exist; otherwise, it + re-uses the existing {@link android.support.v4.content.CursorLoader}. The loader framework + tracks {@link android.support.v4.content.CursorLoader} instance using the <code>id</code> + value passed to {@link android.support.v4.app.LoaderManager#initLoader initLoader()}. +</p> +<h2 id="DefineLaunch">Define and Launch the Query</h2> +<p> + To create a {@link android.support.v4.content.CursorLoader} and define its + query at the same time, call the constructor +{@link android.support.v4.content.CursorLoader#CursorLoader(Context, Uri, String[], String, String[], String) + CursorLoader(context, uri, projection, selection, selectionArgs, sortOrder)}. The + <code>context</code> and <code>uri</code> arguments are required, but the others are optional. + To use the default value for an optional argument, pass in <code>null</code>. The + {@link android.support.v4.content.CursorLoader} runs the query against the + {@link android.content.ContentProvider} identified by <code>uri</code>, just as if you had + called {@link android.content.ContentResolver#query ContentResolver.query()} with the same + arguments. +</p> +<p> + For example: +</p> +<pre> +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: + /* + * Return a new CursorLoader + */ + return new CursorLoader( + this, // Context + DataProviderContract.IMAGE_URI, // Provider's content URI + PROJECTION, // Columns to return + null, // Return all rows + null, // No search arguments + null); // Default search order + default: + // An invalid id was passed in + return null; + } +} +</pre> diff --git a/docs/html/training/load-data-background/handle-results.jd b/docs/html/training/load-data-background/handle-results.jd new file mode 100644 index 000000000000..f8e003a3401f --- /dev/null +++ b/docs/html/training/load-data-background/handle-results.jd @@ -0,0 +1,104 @@ +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">Clear Out Old Data</a></li> +</ol> + </div> +</div> + +<p> + {@link android.support.v4.content.CursorLoader} returns its query results to your + implementation of + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished + LoaderCallbacks.onLoadFinished()}, in the form of a {@link android.database.Cursor}. In the + callback, you can update your data display, do further processing on the + {@link android.database.Cursor} data, and so forth. +</p> +<p> + When the loader framework detects changes to data associated with the query, + it resets the {@link android.support.v4.content.CursorLoader}, closes the current + {@link android.database.Cursor}, and then invokes your implementation of + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}. + Use this callback to delete references to the current {@link android.database.Cursor}; when the + loader framework destroys the {@link android.database.Cursor}, you won't have outstanding + references that cause memory leaks. +</p> +<h2 id="HandleFinished">Handle Query Results</h2> +<p> + The following two snippets are an example of displaying the results of a query, using a + {@link android.widget.ListView} backed by a + {@link android.support.v4.widget.SimpleCursorAdapter}. +</p> +<p> + The first snippet shows the {@link android.widget.ListView} and + {@link android.support.v4.widget.SimpleCursorAdapter}: +</p> +<pre> +// Gets a handle to the Android built-in ListView widget +mListView = ((ListView) findViewById(android.R.id.list)); +// Creates a CursorAdapter +mAdapter = + new SimpleCursorAdapter( + this, // Current context + R.layout.logitem, // View for each item in the list + null, // Don't provide the cursor yet + FROM_COLUMNS, // List of cursor columns to display + TO_FIELDS, // List of TextViews in each line + 0 // flags +); +// Links the adapter to the ListView +mListView.setAdapter(mAdapter); +</pre> +<p> + The next snippet shows an implementation of + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished onLoadFinished()} + that moves the query results in the returned {@link android.database.Cursor} to the + {@link android.support.v4.widget.SimpleCursorAdapter}. Changing the + {@link android.database.Cursor} in the + {@link android.support.v4.widget.SimpleCursorAdapter} triggers a refresh of the + {@link android.widget.ListView} with the new data: +</p> +<pre> +public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) +{ + /* + * Move the results into the adapter. This + * triggers the ListView to re-display. + */ + mAdapter.swapCursor(cursor); +} +</pre> +<h2 id="HandleReset">Handle a Loader Reset</h2> +<p> + The loader framework resets the {@link android.support.v4.content.CursorLoader} whenever the + {@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, make sure to prevent memory leaks by deleting all references to the current + {@link android.database.Cursor}. Once you return from + {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset onLoaderReset()}, + the loader framework re-runs the query. +</p> +<p> + For example: +</p> +<pre> +public void onLoaderReset(Loader<Cursor> loader) +{ + // Remove the reference to the current Cursor + mAdapter.swapCursor(null); +} +</pre> diff --git a/docs/html/training/load-data-background/index.jd b/docs/html/training/load-data-background/index.jd new file mode 100644 index 000000000000..574a32cc0e40 --- /dev/null +++ b/docs/html/training/load-data-background/index.jd @@ -0,0 +1,117 @@ +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> +<h3>Dependencies</h3> +<ul> + <li> + Android 1.6 or later + </li> +</ul> +<h3>Prerequisites</h3> +<ul> + <li> + <a href="{@docRoot}training/basics/firstapp/index.html">Building Your First App</a> class + </li> + <li> + <a href="{@docRoot}training/basics/activity-lifecycle/index.html"> + Managing the Activity Lifecycle</a> class + </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> +</div> +</div> +<p> + A {@link android.support.v4.content.CursorLoader} runs a query against a + {@link android.content.ContentProvider} on a background thread and returns a + {@link android.database.Cursor} to the main thread. +</p> +<p> + {@link android.support.v4.content.CursorLoader} has these advantages over alternate ways of + running a query: +</p> +<dl> + <dt> + Query on a background thread + </dt> + <dd> + A {@link android.support.v4.content.CursorLoader} query runs asynchronously on a + background thread, so it doesn't cause "Application Not Responding" (ANR) errors on the UI + thread. {@link android.support.v4.content.CursorLoader} creates and starts the + background thread; all you have to do is initialize the loader framework and handle the + results of the query. + </dd> + <dt> + Automatic re-query + </dt> + <dd> + A {@link android.support.v4.content.CursorLoader} automatically runs a new query when + the loader framework detects that the data underlying the {@link android.database.Cursor} + has changed. + </dd> + <dt> + Simple API + </dt> + <dd> + The {@link android.support.v4.content.CursorLoader} API provides the + query framework and cursor monitoring that you would have to define yourself if you used + {@link android.os.AsyncTask}. + </dd> +</dl> +<p> + A {@link android.support.v4.content.CursorLoader} is limited in that the query must be + against a {@link android.net.Uri} and must return a {@link android.database.Cursor}. Because of + this, a {@link android.support.v4.content.CursorLoader} can only run a query against a + {@link android.content.ContentProvider}. +</p> +<p> + This class describes how to define and use a {@link android.support.v4.content.CursorLoader}. + 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">Setting Up the Loader</a></strong> + </dt> + <dd> + Learn how to set up an {@link android.app.Activity} that inherits the necessary classes + for running a {@link android.support.v4.content.CursorLoader} and returning results. + </dd> + <dt> + <strong><a href="define-launch-query.html">Defining and Launching the Query</a></strong> + </dt> + <dd> + Learn how to perform a query against a {@link android.content.ContentProvider} 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> diff --git a/docs/html/training/load-data-background/setup-loader.jd b/docs/html/training/load-data-background/setup-loader.jd new file mode 100644 index 000000000000..4b406116ff6c --- /dev/null +++ b/docs/html/training/load-data-background/setup-loader.jd @@ -0,0 +1,90 @@ +page.title=Setting Up the Loader +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="#AddExtensions">Extend an Activity</a> + </li> + <li> + <a href="#GetLoader">Retrieve a LoaderManager</a> + </li> + <li> + <a href="#InitializeLoader">Initialize the Loader Framework</a> + </li> +</ol> + </div> +</div> +<p> + You create a {@link android.support.v4.content.CursorLoader} within a + <b>loader framework</b>. To set up the framework, you implement the + {@link android.support.v4.app.LoaderManager.LoaderCallbacks LoaderCallbacks<Cursor>} + as part of an {@link android.app.Activity}. In addition, to provide compatibility + compatible with platform versions starting with Android 1.6, you must extend the + {@link android.app.Activity} with the {@link android.support.v4.app.FragmentActivity} class. +</p> +<p class="note"> + <strong>Note:</strong> A {@link android.support.v4.app.Fragment} is not a prerequisite for + {@link android.support.v4.content.CursorLoader}. As a convenience, the support library class + {@link android.support.v4.app.FragmentActivity} contains the fragment and the loader frameworks, + but they are completely independent of each other. +</p> +<p> + Before you can use the loader framework, you need to initialize it. To do this, retrieve + a {@link android.support.v4.app.LoaderManager} object and call its + {@link android.support.v4.app.LoaderManager#initLoader initLoader()} method. +</p> +<p> + If you do use one or more {@link android.support.v4.app.Fragment} objects in an + {@link android.app.Activity}, the {@link android.support.v4.app.LoaderManager} you retrieve is + available to all of them. +</p> +<h2 id="AddExtensions">Extend an Activity</h2> +<p> + To set up an {@link android.app.Activity} subclass to contain a + {@link android.support.v4.content.CursorLoader}, extend the subclass with + must extend {@link android.support.v4.app.FragmentActivity}, which provides the loader + framework, and implement the {@link android.support.v4.app.LoaderManager.LoaderCallbacks + LoaderCallbacks<Cursor>} interface, which specifies method signatures that the loader + framework uses to interact with the {@link android.app.Activity}. +</p> +<p> + For example: +</p> +<pre> +public class DisplayActivity extends FragmentActivity + implements LoaderManager.LoaderCallbacks<Cursor> +</pre> +<h2 id="GetLoader">Retrieve a LoaderManager</h2> +<p> + To get an instance {@link android.support.v4.app.LoaderManager} for use in your + {@link android.app.Activity}, call + {@link android.support.v4.app.FragmentActivity#getSupportLoaderManager + FragmentActivity.getSupportLoaderManager()} at the beginning of the + {@link android.app.Activity#onCreate onCreate()} method. For example: +</p> +<pre> +private LoaderManager mLoaderManager; +public void onCreate() { +... +mLoaderManager = this.getSupportLoaderManager(); +</pre> +<h2 id="InitializeLoader">Initialize the Loader Framework</h2> +<p> + Once you have the {@link android.support.v4.app.LoaderManager} object, initialize + it by calling {@link android.support.v4.app.LoaderManager#initLoader initLoader()}. For + example: +</p> +<pre> +// CursorLoader instance identifier +public static final int URL_LOADER = 0; +... +// Initializes the CursorLoader +getSupportLoaderManager().initLoader(URL_LOADER, null, this); +</pre> diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 4a5b0fadc5dd..1c85ae840188 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -58,7 +58,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/basics/supporting-devices/index.html"> <span class="en">Supporting Different Devices</span> @@ -78,7 +78,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/basics/fragments/index.html"> <span class="en">Building a Dynamic UI with Fragments</span> @@ -143,9 +143,9 @@ </ul> </li> - + </ul> - </li><!-- end basic training --> + </li><!-- end basic training --> <li class="nav-section"> <div class="nav-section-header"> <a href="<?cs var:toroot ?>training/advanced.html"> @@ -193,7 +193,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/efficient-downloads/index.html"> <span class="en">Transferring Data Without Draining the Battery</span> @@ -233,12 +233,12 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/multiscreen/index.html" zh-CN-lang="针对多种屏幕进行设计" ja-lang="複数画面のデザイン" - es-lang="Cómo diseñar aplicaciones para varias pantallas" + es-lang="Cómo diseñar aplicaciones para varias pantallas" >Designing for Multiple Screens</a> </div> <ul> @@ -246,24 +246,24 @@ zh-CN-lang="支持各种屏幕尺寸" ko-lang="다양한 화면 크기 지원" ja-lang="さまざまな画面サイズのサポート" - es-lang="Cómo admitir varios tamaños de pantalla" + es-lang="Cómo admitir varios tamaños de pantalla" >Designing for Multiple Screens</a> </li> <li><a href="<?cs var:toroot ?>training/multiscreen/screendensities.html" zh-CN-lang="支持各种屏幕密度" ja-lang="さまざまな画面密度のサポート" - es-lang="Cómo admitir varias densidades de pantalla" + es-lang="Cómo admitir varias densidades de pantalla" >Supporting Different Screen Densities</a> </li> <li><a href="<?cs var:toroot ?>training/multiscreen/adaptui.html" zh-CN-lang="实施自适应用户界面流程" ja-lang="順応性のある UI フローの実装" - es-lang="Cómo implementar interfaces de usuario adaptables" + es-lang="Cómo implementar interfaces de usuario adaptables" >Implementing Adaptive UI Flows</a> </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/improving-layouts/index.html"> <span class="en">Improving Layout Performance</span> @@ -335,37 +335,37 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/monitoring-device-state/index.html" zh-CN-lang="优化电池使用时间" ja-lang="電池消費量の最適化" - es-lang="Cómo optimizar la duración de la batería" + es-lang="Cómo optimizar la duración de la batería" >Optimizing Battery Life</a> </div> <ul> <li><a href="<?cs var:toroot ?>training/monitoring-device-state/battery-monitoring.html" zh-CN-lang="监控电池电量和充电状态" ja-lang="電池残量と充電状態の監視" - es-lang="Cómo controlar el nivel de batería y el estado de carga" + es-lang="Cómo controlar el nivel de batería y el estado de carga" >Monitoring the Battery Level and Charging State</a> </li> <li><a href="<?cs var:toroot ?>training/monitoring-device-state/docking-monitoring.html" zh-CN-lang="确定和监控基座对接状态和类型" ja-lang="ホルダーの装着状態とタイプの特定と監視" - es-lang="Cómo determinar y controlar el tipo de conector y el estado de la conexión" + es-lang="Cómo determinar y controlar el tipo de conector y el estado de la conexión" >Determining and Monitoring the Docking State and Type</a> </li> <li><a href="<?cs var:toroot ?>training/monitoring-device-state/connectivity-monitoring.html" zh-CN-lang="确定和监控网络连接状态" ja-lang="接続状態の特定と監視" - es-lang="Cómo determinar y controlar el estado de la conectividad" + es-lang="Cómo determinar y controlar el estado de la conectividad" >Determining and Monitoring the Connectivity Status</a> </li> <li><a href="<?cs var:toroot ?>training/monitoring-device-state/manifest-receivers.html" zh-CN-lang="根据需要操作广播接收器" ja-lang="オンデマンドでのブロードキャスト レシーバ操作" - es-lang="Cómo manipular los receptores de emisión bajo demanda" + es-lang="Cómo manipular los receptores de emisión bajo demanda" >Manipulating Broadcast Receivers On Demand</a> </li> </ul> @@ -455,7 +455,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/camera/index.html"> <span class="en">Capturing Photos</span> @@ -475,7 +475,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/multiple-apks/index.html"> <span class="en">Maintaining Multiple APKs</span> @@ -535,7 +535,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/monetization/index.html"> <span class="en">Monetizing Your App</span> @@ -547,7 +547,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/design-navigation/index.html"> <span class="en">Designing Effective Navigation</span> @@ -620,7 +620,7 @@ </li> </ul> </li> - + <li class="nav-section"> <div class="nav-section-header"><a href="<?cs var:toroot ?>training/displaying-bitmaps/index.html"> <span class="en">Displaying Bitmaps Efficiently</span> @@ -717,6 +717,25 @@ </ul> </li> + <li class="nav-section"> + <div class="nav-section-header"><a href="<?cs var:toroot ?>training/load-data-background/index.html"> + <span class="en">Loading Data in the Background</span> + </a></div> + <ul> + <li><a href="<?cs var:toroot ?>training/load-data-background/setup-loader.html"> + <span class="en">Setting Up the Loader</span> + </a> + </li> + <li><a href="<?cs var:toroot ?>training/load-data-background/define-launch-query.html"> + <span class="en">Defining and Launching the Query</span> + </a> + </li> + <li><a href="<?cs var:toroot ?>training/load-data-background/handle-results.html"> + <span class="en">Handling the Results</span> + </a> + </li> + </ul> + </li> </ul> </li> |