Android Training: CursorLoader
Change-Id: Ia8d723b5ce32002597b9444b8c7eff07b1ab29c8
This commit is contained in:
@@ -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>
|
||||||
104
docs/html/training/load-data-background/handle-results.jd
Normal file
104
docs/html/training/load-data-background/handle-results.jd
Normal file
@@ -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>
|
||||||
117
docs/html/training/load-data-background/index.jd
Normal file
117
docs/html/training/load-data-background/index.jd
Normal file
@@ -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>
|
||||||
90
docs/html/training/load-data-background/setup-loader.jd
Normal file
90
docs/html/training/load-data-background/setup-loader.jd
Normal file
@@ -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>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/basics/supporting-devices/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/basics/supporting-devices/index.html">
|
||||||
<span class="en">Supporting Different Devices</span>
|
<span class="en">Supporting Different Devices</span>
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/basics/fragments/index.html">
|
<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>
|
<span class="en">Building a Dynamic UI with Fragments</span>
|
||||||
@@ -143,9 +143,9 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li><!-- end basic training -->
|
</li><!-- end basic training -->
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header">
|
<div class="nav-section-header">
|
||||||
<a href="<?cs var:toroot ?>training/advanced.html">
|
<a href="<?cs var:toroot ?>training/advanced.html">
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/efficient-downloads/index.html">
|
<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>
|
<span class="en">Transferring Data Without Draining the Battery</span>
|
||||||
@@ -233,12 +233,12 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/multiscreen/index.html"
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/multiscreen/index.html"
|
||||||
zh-CN-lang="针对多种屏幕进行设计"
|
zh-CN-lang="针对多种屏幕进行设计"
|
||||||
ja-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>
|
>Designing for Multiple Screens</a>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -246,24 +246,24 @@
|
|||||||
zh-CN-lang="支持各种屏幕尺寸"
|
zh-CN-lang="支持各种屏幕尺寸"
|
||||||
ko-lang="다양한 화면 크기 지원"
|
ko-lang="다양한 화면 크기 지원"
|
||||||
ja-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>
|
>Designing for Multiple Screens</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="<?cs var:toroot ?>training/multiscreen/screendensities.html"
|
<li><a href="<?cs var:toroot ?>training/multiscreen/screendensities.html"
|
||||||
zh-CN-lang="支持各种屏幕密度"
|
zh-CN-lang="支持各种屏幕密度"
|
||||||
ja-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>
|
>Supporting Different Screen Densities</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="<?cs var:toroot ?>training/multiscreen/adaptui.html"
|
<li><a href="<?cs var:toroot ?>training/multiscreen/adaptui.html"
|
||||||
zh-CN-lang="实施自适应用户界面流程"
|
zh-CN-lang="实施自适应用户界面流程"
|
||||||
ja-lang="順応性のある UI フローの実装"
|
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>
|
>Implementing Adaptive UI Flows</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/improving-layouts/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/improving-layouts/index.html">
|
||||||
<span class="en">Improving Layout Performance</span>
|
<span class="en">Improving Layout Performance</span>
|
||||||
@@ -335,37 +335,37 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/monitoring-device-state/index.html"
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/monitoring-device-state/index.html"
|
||||||
zh-CN-lang="优化电池使用时间"
|
zh-CN-lang="优化电池使用时间"
|
||||||
ja-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>
|
>Optimizing Battery Life</a>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/battery-monitoring.html"
|
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/battery-monitoring.html"
|
||||||
zh-CN-lang="监控电池电量和充电状态"
|
zh-CN-lang="监控电池电量和充电状态"
|
||||||
ja-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>
|
>Monitoring the Battery Level and Charging State</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/docking-monitoring.html"
|
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/docking-monitoring.html"
|
||||||
zh-CN-lang="确定和监控基座对接状态和类型"
|
zh-CN-lang="确定和监控基座对接状态和类型"
|
||||||
ja-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>
|
>Determining and Monitoring the Docking State and Type</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/connectivity-monitoring.html"
|
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/connectivity-monitoring.html"
|
||||||
zh-CN-lang="确定和监控网络连接状态"
|
zh-CN-lang="确定和监控网络连接状态"
|
||||||
ja-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>
|
>Determining and Monitoring the Connectivity Status</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/manifest-receivers.html"
|
<li><a href="<?cs var:toroot ?>training/monitoring-device-state/manifest-receivers.html"
|
||||||
zh-CN-lang="根据需要操作广播接收器"
|
zh-CN-lang="根据需要操作广播接收器"
|
||||||
ja-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>
|
>Manipulating Broadcast Receivers On Demand</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -455,7 +455,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/camera/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/camera/index.html">
|
||||||
<span class="en">Capturing Photos</span>
|
<span class="en">Capturing Photos</span>
|
||||||
@@ -475,7 +475,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/multiple-apks/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/multiple-apks/index.html">
|
||||||
<span class="en">Maintaining Multiple APKs</span>
|
<span class="en">Maintaining Multiple APKs</span>
|
||||||
@@ -535,7 +535,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/monetization/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/monetization/index.html">
|
||||||
<span class="en">Monetizing Your App</span>
|
<span class="en">Monetizing Your App</span>
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/design-navigation/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/design-navigation/index.html">
|
||||||
<span class="en">Designing Effective Navigation</span>
|
<span class="en">Designing Effective Navigation</span>
|
||||||
@@ -620,7 +620,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-section">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/displaying-bitmaps/index.html">
|
<div class="nav-section-header"><a href="<?cs var:toroot ?>training/displaying-bitmaps/index.html">
|
||||||
<span class="en">Displaying Bitmaps Efficiently</span>
|
<span class="en">Displaying Bitmaps Efficiently</span>
|
||||||
@@ -717,6 +717,25 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
Reference in New Issue
Block a user