`

【翻译】(5)加载器

 
阅读更多

【翻译】(5)加载器

 

see

http://developer.android.com/guide/topics/fundamentals/loaders.html

 

原文见

http://developer.android.com/guide/topics/fundamentals/loaders.html

 

-------------------------------

 

Loaders

 

加载器

 

-------------------------------

 

In this document

 

本文目录

 

* Loader API Summary 加载器摘要

* Using Loaders in an Application 在应用程序中使用加载器

* Starting a Loader 启动加载器

* Restarting a Loader 重启加载器

* Using the LoaderManager Callbacks 使用LoaderManager回调

* Example 示例

* More Examples 更多示例

 

Key classes

 

关键类

 

* LoaderManager

* Loader

 

Related samples

 

相关示例

 

LoaderCursor

LoaderThrottle

 

-------------------------------

 

Introduced in Android 3.0, loaders make it easy to asynchronously load data in an activity or fragment. Loaders have these characteristics:

 

在Android 3.0内引入,加载器使在活动或片段内异步加载数据变得容易。加载器有这些特性:

 

* They are available to every Activity and Fragment.

 

* 它们对于每个活动和片段是可用的。

 

* They provide asynchronous loading of data.

 

* 它们提供数据的异步加载。

 

* They monitor the source of their data and deliver new results when the content changes.

 

* 它们监视它们的数据源并且在内容改变时派发新的结果。

 

* They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.

 

* 当在配置改变后它们正在重建时,它们会自动重连至最后的加载器游标。这么一来,它们就不需要重新查询它们的数据。

 

-------------------------------

 

Loader API Summary

 

加载器API摘要

 

There are multiple classes and interfaces that may be involved in using loaders in an application. They are summarized in this table:

 

在应用程序中使用加载器可能会涉及多个类和接口。它们总结在这个表格中:

 

-------------------------------

 

Class/Interface Description

 

类/接口 描述

 

* LoaderManager An abstract class associated with an Activity or Fragment for managing one or more Loader instances. This helps an application manage longer-running operations in conjunction with the Activity or Fragment lifecycle; the most common use of this is with a CursorLoader, however applications are free to write their own loaders for loading other types of data. 

 

* LoaderManager:一个抽象类,与活动或片段关联,用于管理一个或多个加载器实例。它帮助应用程序管理长期运行的操作,与活动或片段的生命周期相结合;它最常见的用法是使用CursorLoader,然而应用程序可以自由书写它们自己的加载器用于加载其它类型的数据。

 

There is only one LoaderManager per activity or fragment. But a LoaderManager can have multiple loaders.

 

每个活动或片段只有一个LoaderManager。但一个LoaderManager可以拥有多个加载器。

 

* LoaderManager.LoaderCallbacks A callback interface for a client to interact with the LoaderManager. For example, you use the onCreateLoader() callback method to create a new loader.

 

* LoaderManager.LoaderCallbacks:回调接口,用于客户端与LoaderManager的交互。例如,你使用onCreateLoader()回调方法创建新的加载器。

 

* Loader An abstract class that performs asynchronous loading of data. This is the base class for a loader. You would typically use CursorLoader, but you can implement your own subclass. While loaders are active they should monitor the source of their data and deliver new results when the contents change.

 

* 加载器:一个抽象类,执行数据的异步加载。它是加载器的基类。你通常使用CursorLoader,但你可以实现你自己的子类。当加载器被激活时,它们应该会监视它们的数据源并且当内容改变时派发新的结果。

 

* AsyncTaskLoader Abstract loader that provides an AsyncTask to do the work.

 

* AsyncTaskLoader:抽象加载器,提供一个AsyncTask完成工作。

 

* CursorLoader A subclass of AsyncTaskLoader that queries the ContentResolver and returns a Cursor. This class implements the Loader protocol in a standard way for querying cursors, building on AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. Using this loader is the best way to asynchronously load data from a ContentProvider, instead of performing a managed query through the fragment or activity's APIs.

 

* CursorLoader:AsyncTaskLoader的子类,查询ContentResolver并且返回一个Cursor对象。此类以查询游标的标准形式实现Loader协议,在AsyncTaskLoader上构建,在后台线程中执行游标查询以致它不会阻塞应用程序的用户界面。使用此加载器是异步从ContentProvider加载数据的最佳方法,代替通过片段或活动API执行的托管查询。

 

-------------------------------

 

The classes and interfaces in the above table are the essential components you'll use to implement a loader in your application. You won't need all of them for each loader you create, but you'll always need a reference to the LoaderManager in order to initialize a loader and an implementation of a Loader class such as CursorLoader. The following sections show you how to use these classes and interfaces in an application.

 

上表中的类和接口是你将用于在你的应用程序中实现加载器的本质组件。对于你创建的每个加载器,你将不需要它们的全部,但你将总是需要一个指向LoaderManager的引用,以便初始化一个加载器和一个加载器类的实现诸如CursorLoader。以下章节向你展示如何在应用程序中使用这些类和接口。

 

-------------------------------

 

Using Loaders in an Application

 

在应用程序中使用加载器

 

This section describes how to use loaders in an Android application. An application that uses loaders typically includes the following:

 

此章节描述如何在一个Android应用程序中使用加载器。一个使用加载器的应用程序通常包括以下内容:

 

* An Activity or Fragment.

 

* 一个活动或片段。

 

* An instance of the LoaderManager.

 

* 一个LoaderManager实例。

 

* A CursorLoader to load data backed by a ContentProvider. Alternatively, you can implement your own subclass of Loader or AsyncTaskLoader to load data from some other source.

 

* 一个用于加载由ContentProvider提供的数据的CursorLoader。可选地,你可以实现你自己的Loader或AsyncTaskLoader的子类,以加载来自其它源的数据。

 

* An implementation for LoaderManager.LoaderCallbacks. This is where you create new loaders and manage your references to existing loaders.

 

LoaderManager.LoaderCallbacks的实现。在这个回调中你创建新的加载器并管理你的现存加载器的引用。

 

* A way of displaying the loader's data, such as a SimpleCursorAdapter.

 

* 一个显示加载器数据的方式,诸如一个SimpleCursorAdapter

 

* A data source, such as a ContentProvider, when using a CursorLoader.

 

* 一个数据源,诸如ContentProvider,当使用CursorLoader时。

 

Starting a Loader

 

启动加载器

 

The LoaderManager manages one or more Loader instances within an Activity or Fragment. There is only one LoaderManager per activity or fragment.

 

在活动或片段中,LoaderManager管理一个或多个加载器实例。每个活动或片段只有一个LoaderManager。

 

You typically initialize a Loader within the activity's onCreate() method, or within the fragment's onActivityCreated() method. You do this as follows:

 

你通常在活动的onCreate()内,或在片段的onActivityCreated()方法内初始化一个Loader。你可以像如下所示做到这一点:

 

-------------------------------

 

// Prepare the loader.  Either re-connect with an existing one,

// or start a new one.

// 准备加载器。要么用现存加载器重连,要么启动新的加载器。

getLoaderManager().initLoader(0, null, this);

 

-------------------------------

 

The initLoader() method takes the following parameters:

 

initLoader()方法传入以下参数:

 

* A unique ID that identifies the loader. In this example, the ID is 0.

 

* 一个标识加载器的唯一ID。在这个示例中,ID是0.

 

* Optional arguments to supply to the loader at construction (null in this example).

 

* 在构造函数中提供给加载器的可选参数(此示例中为null)

 

* A LoaderManager.LoaderCallbacks implementation, which the LoaderManager calls to report loader events. In this example, the local class implements the LoaderManager.LoaderCallbacks interface, so it passes a reference to itself, this.

 

* 一个LoaderManager.LoaderCallbacks实现,它被LoaderManager调用来报告加载器事件。在此示例中,内部类实现LoaderManager.LoaderCallbacks接口,所以它传递指向它自己的引用this。

 

The initLoader() call ensures that a loader is initialized and active. It has two possible outcomes:

 

initLoader()的调用确保加载器被初始化并激活。它有两个可能的结果:

 

* If the loader specified by the ID already exists, the last created loader is reused.

 

* 如果加载器由现存的ID指定,最后创建的加载器会被重用。

 

* If the loader specified by the ID does not exist, initLoader() triggers the LoaderManager.LoaderCallbacks method onCreateLoader(). This is where you implement the code to instantiate and return a new loader. For more discussion, see the section onCreateLoader.

 

* 如果加载器由不存在的ID指定,那么initLoader()触发LoaderManager.LoaderCallbacks的方法onCreateLoader()。在此方法中你的实现代码初始化并返回新的加载器。更多讨论,请参看onCreateLoader章节。

 

In either case, the given LoaderManager.LoaderCallbacks implementation is associated with the loader, and will be called when the loader state changes. If at the point of this call the caller is in its started state, and the requested loader already exists and has generated its data, then the system calls onLoadFinished() immediately (during initLoader()), so you must be prepared for this to happen. See onLoadFinished for more discussion of this callback

 

不管是两种情况中的哪一种,指定的LoaderManager.LoaderCallbacks实现被关联到加载器,并在加载器状态改变时被调用。如果在此调用的发生点上调用者正处于它的被启动状态,并且请求的加载器已经存在,以及已经生成它的数据,那么系统立刻调用onLoadFinished()(在initLoader()期间),所以你必须准备它要发生。参看onLoadFinished以获取关于此回调的更多讨论。

 

Note that the initLoader() method returns the Loader that is created, but you don't need to capture a reference to it. The LoaderManager manages the life of the loader automatically. The LoaderManager starts and stops loading when necessary, and maintains the state of the loader and its associated content. As this implies, you rarely interact with loaders directly (though for an example of using loader methods to fine-tune a loader's behavior, see the LoaderThrottle sample). You most commonly use the LoaderManager.LoaderCallbacks methods to intervene in the loading process when particular events occur. For more discussion of this topic, see Using the LoaderManager Callbacks.

 

注意initLoader()方法返回被创建的加载器,但你不需要捕捉它的引用。LoaderManager自动管理加载器的生命。在需要时LoaderManager启动和停止加载,并维护加载器的状态以及它所关联的内容。正如它所暗示的,你很少直接与加载器交互(但对于使用加载器方法以微调加载器的行为的示例则不然,请参考LoaderThrottle示例)。最常见的是,当特殊的事件发生时,你使用LoaderManager.LoaderCallbacks方法干预加载的过程。关于此问题的更多讨论,请参考LoaderManager回调的使用。

 

Restarting a Loader

 

重启加载器

 

When you use initLoader(), as shown above, it uses an existing loader with the specified ID if there is one. If there isn't, it creates one. But sometimes you want to discard your old data and start over.

 

当你使用initLoader(),正如上面演示的那样,它使用一个带指定ID的现存加载器,如果有的话。如果没有,它会创建一个ID。但有时你需要丢弃你的旧数据并重新开始。

 

To discard your old data, you use restartLoader(). For example, this implementation of SearchView.OnQueryTextListener restarts the loader when the user's query changes. The loader needs to be restarted so that it can use the revised search filter to do a new query:

 

为了丢弃你的旧数据,你使用restartLoader()。例如,这个SearchView.OnQueryTextListener实现当用户查询改变时重启加载器。加载器需要重启以致使它可以使用被修改的搜索过滤器以完成新的查询:

 

-------------------------------

 

public boolean onQueryTextChanged(String newText) {

    // Called when the action bar search text has changed.  Update

    // the search filter, and restart the loader to do a new query

    // with this filter.

// 当动作栏搜索文本被修改时调用。

// 更新搜索过滤器,并重启加载器以用此过滤器完成新的查询。

    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;

    getLoaderManager().restartLoader(0, null, this);

    return true;

}

 

-------------------------------

 

Using the LoaderManager Callbacks

 

使用LoaderManager回调

 

LoaderManager.LoaderCallbacks is a callback interface that lets a client interact with the LoaderManager.

 

LoaderManager.LoaderCallbacks是一个回调接口,让一个客户端与LoaderManager交互。

 

Loaders, in particular CursorLoader, are expected to retain their data after being stopped. This allows applications to keep their data across the activity or fragment's onStop() and onStart() methods, so that when users return to an application, they don't have to wait for the data to reload. You use the LoaderManager.LoaderCallbacks methods when to know when to create a new loader, and to tell the application when it is time to stop using a loader's data.

 

加载器,尤其是CursorLoader,期待在它被停止之后保持其数据。允许应用程序跨活动或片段的onStop()和onStart()方法保持其数据,以致当用户返回到应用程序时,他们不必等待数据重新加载。当你想知道何时创建一个新加载器时,你会使用LoaderManager.LoaderCallbacks方法,它会在停止使用加载器数据的时候立刻告诉应用程序。

 

LoaderManager.LoaderCallbacks includes these methods:

 

LoaderManager.LoaderCallbacks包含这些方法:

 

* onCreateLoader() — Instantiate and return a new Loader for the given ID.

 

* onCreateLoader()——初始化并返回给定ID的新加载器

 

* onLoadFinished() — Called when a previously created loader has finished its load.

 

* onLoadFinished()——当之前被创建的加载器已经完成其加载时被调用。

 

* onLoaderReset() — Called when a previously created loader is being reset, thus making its data unavailable.

 

* onLoaderReset()——当之前创建的加载器被重置时被创建,它使其数据不可用。

 

These methods are described in more detail in the following sections.

 

在下面的章节中会详细描述这些方法。

 

onCreateLoader

 

When you attempt to access a loader (for example, through initLoader()), it checks to see whether the loader specified by the ID exists. If it doesn't, it triggers the LoaderManager.LoaderCallbacks method onCreateLoader(). This is where you create a new loader. Typically this will be a CursorLoader, but you can implement your own Loader subclass.

 

当你尝试访问一个加载器(例如,通过initLoader()),它检查ID指定的加载器是否存在。如果不存在,它触发LoaderManager.LoaderCallbacks方法onCreateLoader()。在这个方法里你创建新的加载器。通常它是一个CursorLoader,但你可以实现你自己的Loader子类。

 

In this example, the onCreateLoader() callback method creates a CursorLoader. You must build the CursorLoader using its constructor method, which requires the complete set of information needed to perform a query to the ContentProvider. Specifically, it needs:

 

在这个示例中,onCreateLoader()回调方法创建一个CursorLoader,你必须使用其构造函数构建CursorLoader对象,该构造函数需要完整的信息集合,需要用其执行对ContentProvider的查询。典型地,它需要:

 

* uri — The URI for the content to retrieve.

 

* uri——获取内容的URI。

 

* projection — A list of which columns to return. Passing null will return all columns, which is inefficient.

 

* projection——返回列的列表。传递null将返回所有列,这样效率较低。

 

* selection — A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given URI.

 

* selection——一个过滤器声明返回的行,被格式化作为SQL WHERE分句(不包含WHERE自身)。传递null将返回所给URI的所有行。

 

* selectionArgs — You may include ?s in the selection, which will be replaced by the values from selectionArgs, in the order that they appear in the selection. The values will be bound as Strings.

 

* selectionArgs——你可能放进selection中的嵌入物,它将被selectionArgs的值替换,根据它们在selection中出现的顺序。这些值将被限制作为String。

 

* sortOrder — How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.

 

* sortOrder——如何排序行,被格式化作为SQL ORDER BY分句(不包括ORDER BY自身)。传递null将使用默认的排序顺序,可能是未排序的。

 

For example:

 

例如:

 

-------------------------------

 

 // If non-null, this is the current filter the user has provided.

 // 如果非空,它是用户提供过的当前过滤器

String mCurFilter;

...

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    // This is called when a new Loader needs to be created.  This

    // sample only has one Loader, so we don't care about the ID.

    // First, pick the base URI to use depending on whether we are

    // currently filtering.

// 当新加载器需要被创建时,这个方法被调用。这个示例只有一个加载器,

// 所以我们不关心ID。首先,根据我们是否正在被过滤,获取要使用的基本URI。

    Uri baseUri;

    if (mCurFilter != null) {

        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,

                  Uri.encode(mCurFilter));

    } else {

        baseUri = Contacts.CONTENT_URI;

    }

 

    // Now create and return a CursorLoader that will take care of

    // creating a Cursor for the data being displayed.

    // 现在创建和返回CursorLoader对象,它将负责创建用于要显示数据的游标。

    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("

            + Contacts.HAS_PHONE_NUMBER + "=1) AND ("

            + Contacts.DISPLAY_NAME + " != '' ))";

    return new CursorLoader(getActivity(), baseUri,

            CONTACTS_SUMMARY_PROJECTION, select, null,

            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");

}

 

-------------------------------

 

onLoadFinished

 

This method is called when a previously created loader has finished its load. This method is guaranteed to be called prior to the release of the last data that was supplied for this loader. At this point you should remove all use of the old data (since it will be released soon), but should not do your own release of the data since its loader owns it and will take care of that.

 

当之前创建的加载器已经完成其加载时,此方法被调用。此方法保证在提供给加载器的最后数据释放之前被调用。在这个时间点上你应该移除所有对旧数据的使用(因为它将在不久后被释放),但不应该进行你自己的数据释放,因为它的加载器拥有它并将负责完成这些工作。

 

The loader will release the data once it knows the application is no longer using it. For example, if the data is a cursor from a CursorLoader, you should not call close() on it yourself. If the cursor is being placed in a CursorAdapter, you should use the swapCursor() method so that the old Cursor is not closed. For example:

 

加载器将释放数据,一旦它知道应用程序不再使用。例如,如果数据是一个来自CursorLoader的游标,那么你不应该自己对它调用close()。如果游标被放置进CursorAdapter,你应该使用swapCursor()方法,以致使旧的游标不被关闭。例如:

 

-------------------------------

 

// This is the Adapter being used to display the list's data.

// 这是用于显示列表数据的适配器。

SimpleCursorAdapter mAdapter;

...

 

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

    // Swap the new cursor in.  (The framework will take care of closing the

    // old cursor once we return.)

    // 交换进新的游标。(一旦我们返回,框架将负责关闭旧游标)

    mAdapter.swapCursor(data);

}

 

-------------------------------

 

onLoaderReset

 

This method is called when a previously created loader is being reset, thus making its data unavailable. This callback lets you find out when the data is about to be released so you can remove your reference to it.  

 

当之前被创建的加载器被重置时,此方法被调用,这致使其数据不可用。此回调让你找出数据将在何时被释放,使你可以移除你对它的引用。

 

This implementation calls swapCursor() with a value of null:

 

这里的实现用null值调用swapCursor()。

 

-------------------------------

 

// This is the Adapter being used to display the list's data.

// 这是用于显示列表数据的适配器。

SimpleCursorAdapter mAdapter;

...

 

public void onLoaderReset(Loader<Cursor> loader) {

    // This is called when the last Cursor provided to onLoadFinished()

    // above is about to be closed.  We need to make sure we are no

    // longer using it.

    // 当上面提供给onLoadFinished()的最后Cursor将被关闭时,此方法被调用。

    // 我们需要确保我们不再使用它。

    mAdapter.swapCursor(null);

}

 

-------------------------------

 

Example

 

示例

 

As an example, here is the full implementation of a Fragment that displays a ListView containing the results of a query against the contacts content provider. It uses a CursorLoader to manage the query on the provider.

 

作为例子,这里是片段的完整实现,显示一个ListView,包含对电话簿内容提供者的查询结果。它使用CursorLoader管理对提供者的查询。

 

For an application to access a user's contacts, as shown in this example, its manifest must include the permission READ_CONTACTS.

 

为了让应用程序访问用户的电话簿,正如此示例所示,它的清单必须包含READ_CONTACTS权限。

 

-------------------------------

 

public static class CursorLoaderListFragment extends ListFragment

        implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

 

    // This is the Adapter being used to display the list's data.

    // 这是适配器,用于显示列表数据。

    SimpleCursorAdapter mAdapter;

 

    // If non-null, this is the current filter the user has provided.

    // 如果非空,它是用户提供的当前过滤器。

    String mCurFilter;

 

    @Override public void onActivityCreated(Bundle savedInstanceState) {

        super.onActivityCreated(savedInstanceState);

 

        // Give some text to display if there is no data.  In a real

        // application this would come from a resource.

        // 指定没有数据时显示的文本。

        // 真实应用程序中它应该取自资源。

        setEmptyText("No phone numbers");

 

        // We have a menu item to show in action bar.

        // 我们有菜单条目要显示在动作栏。

        setHasOptionsMenu(true);

 

        // Create an empty adapter we will use to display the loaded data.

        // 创建空的适配器,我们将用它显示被加载的数据。

        mAdapter = new SimpleCursorAdapter(getActivity(),

                android.R.layout.simple_list_item_2, null,

                new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },

                new int[] { android.R.id.text1, android.R.id.text2 }, 0);

        setListAdapter(mAdapter);

 

        // Prepare the loader.  Either re-connect with an existing one,

        // or start a new one.

        // 准备加载器。要么用现存加载器重连,要么启动新的加载器。

        getLoaderManager().initLoader(0, null, this);

    }

 

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

        // Place an action bar item for searching.

        // 放置动作栏条目供搜索。

        MenuItem item = menu.add("Search");

        item.setIcon(android.R.drawable.ic_menu_search);

        item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        SearchView sv = new SearchView(getActivity());

        sv.setOnQueryTextListener(this);

        item.setActionView(sv);

    }

 

    public boolean onQueryTextChange(String newText) {

        // Called when the action bar search text has changed.  Update

        // the search filter, and restart the loader to do a new query

        // with this filter.

        // 当动作栏搜索文本被修改时调用。

        // 更新搜索过滤器,并重启加载器以用此过滤器完成新的查询。

        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;

        getLoaderManager().restartLoader(0, null, this);

        return true;

    }

 

    @Override public boolean onQueryTextSubmit(String query) {

        // Don't care about this.

        // 不要关心这里

        return true;

    }

 

    @Override public void onListItemClick(ListView l, View v, int position, long id) {

        // Insert desired behavior here.

        // 此处插入所需的行为。

        Log.i("FragmentComplexList", "Item clicked: " + id);

    }

 

    // These are the Contacts rows that we will retrieve.

    // 我们将检索的Contacts的行

    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {

        Contacts._ID,

        Contacts.DISPLAY_NAME,

        Contacts.CONTACT_STATUS,

        Contacts.CONTACT_PRESENCE,

        Contacts.PHOTO_ID,

        Contacts.LOOKUP_KEY,

    };

    public Loader<Cursor> onCreateLoader(int id, Bundle args) {

        // This is called when a new Loader needs to be created.  This

        // sample only has one Loader, so we don't care about the ID.

        // First, pick the base URI to use depending on whether we are

        // currently filtering.

        // 当新加载器需要被创建时,这个方法被调用。这个示例只有一个加载器,

        // 所以我们不关心ID。首先,根据我们是否正在被过滤,获取要使用的基本URI。

        Uri baseUri;

        if (mCurFilter != null) {

            baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,

                    Uri.encode(mCurFilter));

        } else {

            baseUri = Contacts.CONTENT_URI;

        }

 

        // Now create and return a CursorLoader that will take care of

        // creating a Cursor for the data being displayed.

        // 现在创建和返回CursorLoader对象,它将负责创建用于要显示数据的游标。

        String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("

                + Contacts.HAS_PHONE_NUMBER + "=1) AND ("

                + Contacts.DISPLAY_NAME + " != '' ))";

        return new CursorLoader(getActivity(), baseUri,

                CONTACTS_SUMMARY_PROJECTION, select, null,

                Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");

    }

 

    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

        // Swap the new cursor in.  (The framework will take care of closing the

        // old cursor once we return.)

        // 交换进新的游标。(一旦我们返回,片段将负责关闭旧游标)

        mAdapter.swapCursor(data);

    }

 

    public void onLoaderReset(Loader<Cursor> loader) {

        // This is called when the last Cursor provided to onLoadFinished()

        // above is about to be closed.  We need to make sure we are no

        // longer using it.

        // 当上面提供给onLoadFinished()的最后Cursor对象将要关闭时调用。

        // 我们需要确保我们不再使用它。

        mAdapter.swapCursor(null);

    }

}

 

-------------------------------

 

More Examples

 

更多示例

 

There are a few different samples in ApiDemos that illustrate how to use loaders:

 

在ApiDemos中有一些不同的示例,描述如何使用加载器:

 

* LoaderCursor — A complete version of the snippet shown above.

 

* LoaderCursor——上面展示代码片段的完整版本。

 

* LoaderThrottle — An example of how to use throttling to reduce the number of queries a content provider does when its data changes.

 

* LoaderThrottle——一个例子,演示如何通过减速,降低内容提供者在其数据改变时出现的请求数量。

 

For information on downloading and installing the SDK samples, see Getting the Samples.

 

关于下载和安装SDK示例的信息,请参看示例的获取。

 

Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.

 

除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。

 

Android 4.0 r1 - 27 Oct 2011 21:16

 

Android 4.0 r1 - 29 Mar 2012 18:25

 

-------------------------------

 

patch:

1. Android 4.0 r1 - 29 Mar 2012 18:25

(1)

reduce the number of queries a content provider does then its data changes.

->

reduce the number of queries a content provider does when its data changes.

 

-------------------------------

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

(此页部分内容基于Android开源项目,以及使用根据创作公共2.5来源许可证中描述的条款进行修改)

 

分享到:
评论

相关推荐

    YUKI:YUKI Galgame翻译器

    YUKI Galgame翻译器 • 紧急公告 2020.5.30晚间,大量用户使用YUKI时遇到错误为ERR: TypeError: Cannot read property 'target' of undefined的报错窗口的ERR: TypeError: Cannot read property 'target' of ...

    http-loader:ngx-translate的加载器,通过http调用加载翻译

    加载程序,使用http加载翻译。 使用ngx-translate的简单示例: ://stackblitz.com/github/ngx-translate/example 在此处获取完整的变更日志: : 安装 我们假设您已经安装了 。 现在,您需要为...

    Java学习笔记

    类加载器 ClassLoader 字节码校验器 解释执行器 (翻译)逐行的解释执行代码 2.安全 健壮 3.面向对象 面向过程: 程序:函数+变量 (算法+数据结构) 面向对象: 如:SmallTalk 程序:对象和对象相互之间的“通讯” ...

    外文翻译 stus MVC

    Figure 5 displays an overview of Struts. Struts overview • Client browser An HTTP request from the client browser creates an event. The Web container will respond with an HTTP response. • ...

    wurst:用于hapi.js路由的基于目录的自动加载器

    用于hapi.js路由的基于目录的自动加载器介绍香肠是基于目录自动加载路线。 只需设置所需的目录结构,导出路由文件,注册插件并根据提供的目录结构获取最终的前缀路由。 例如,它非常适合管理API的各种版本。 香肠是...

    laravel-translation:Laravel应用程序的翻译管理

    以下是功能的完整列表: 文件和数据库驱动程序数据库翻译加载器(当Laravel的翻译检索方法和数据库驱动程序自动从数据库加载翻译) 用于添加新语言以及添加和更新翻译的用户界面Artisan命令来管理您的翻译扫描您的...

    Next.js 插件 + Next.js 10 的 i18n API :globe_showing_Europe-Africa: - 加载页面翻译并以简单的方式使用它们!

    Easy i18n for Next.js +10 Next ...演示 来自 Next.js 的演示 基本演示 复杂演示 没有 webpack 加载器演示 贡献者 :sparkles: 1. 关于 next-translate 这个库的主要目标是在 Next.js 环境中保持翻译尽可能简单。 Nex

    rfc中文文档目录,包含部分翻译

    RFC1605_SONET to Sonnet翻译 RFC1606_用IP版本9的历史观 RFC1611_DNS服务器MIB扩展 RFC1612_DNS解析器MIB扩展 RFC1618_ISDN上的PPP(点对点)协议 RFC1628 UPS 管理信息基础 RFC1633_Internet 体系结构中的综合服务...

    ExHentaiReader:网页级exhentai阅读器(含翻译功能),js脚本实现,无需安装软件,解决ios频繁重签问题

    5、调整了页面布局(可在代码生成器关闭新布局) 6、功能栏添加“原汁原味”功能 1 使用效果 使用前: 使用后: 移动端布局优化 图片铺满 下滑功能栏 标签翻译 2 安装方法 手机浏览器随便打开一个网页,添加书签,...

    Entity Framework 6 Recipes(中文word翻译版)

    关于EF6的正式书籍很少,这个文章是国内翻译整理出来的,共46个小节。适合循序渐进的学习。 第1部分 开始使用实体框架之历史和框架简述 第2部分 开始使用实体框架之使用介绍 第3部分 实体数据建模基础之创建一个简单...

    arabicToEnglish:这个应用程序将帮助阿拉伯人罗马化(而不是翻译)他们的名字

    样式加载器 CSS 加载器 通天塔 现场演示 入门 要启动并运行本地副本,请遵循这些简单的示例步骤。 先决条件 节点.js 设置 通过键入`git clone (在这种情况下,您必须在本地机器上安装git)或从GitHub下载代码的zip...

    Google Android SDK开发范例大全(第3版) 5/5

    9.9 随身翻译机 9.10 通过YouTube ID调用YouTube播放影片 9.11 Google Analytics分析手机用户行为 第10章 创意Android程序设计 10.1 手机手电筒 10.2 GPS轨迹记录器 10.3 女性贴身看护 10.4 手机QR Code二维条形码...

    js特效H5爆炸文字重组效果

    2、由于低版本IE不支持HTML5和CSS3技术,对于部分HTML5模板在IE6、7、8错位问题,请使用360/搜狗浏览器极速模式、Chrome谷歌浏览器、IE9+,FireFox浏览器等查看。 3、不会修改得可以参考此教程进行学习 ...

    corejava基础重要知识点总结

    CLASSPATH:类加载器使用 让类加载器明确去哪里加载.class文件 通常不需要设置 默认值:. .:当前目录(.java) CLASSPATH相当于中国的低保制度 JAVA_HOME:其他的程序使用 WEB 设置方式: 1:一次性的设置 ...

    网络翻译「Web-Translate」-crx插件

    支持PDF和Web的划词翻译插件 1.双击或划译取词. 2.支持发音,翻译弹窗可固定。...5.引入状态管理器,为下一步架构调整与代码重构作准备。 6.优化自动加载脚本的匹配规则 7.自动发音功能 支持语言:中文 (简体)

    前端-web前端-模板-各行各业二十个模板7.13.5

    2、由于低版本IE不支持HTML5和CSS3技术,对于部分HTML5模板在IE6、7、8错位问题,请使用360/搜狗浏览器极速模式、Chrome谷歌浏览器、IE9+,FireFox浏览器等查看。 3、不会修改得可以参考此教程进行学习 ...

    symbolizer:Windows的快速执行跟踪符号器

    dbgeng API用于加载故障转储,并通过查询可用符号来符号化RIP值。 转换以下原始执行跟踪: 0xfffff8053b9ca5c0 0xfffff8053b9ca5c1 0xfffff8053b9ca5c8 0xfffff8053b9ca5d0 0xfffff8053b9ca5d4 0xfffff8053b9ca5...

    Google Android SDK开发范例大全(第3版) 1/5

    9.9 随身翻译机 9.10 通过YouTube ID调用YouTube播放影片 9.11 Google Analytics分析手机用户行为 第10章 创意Android程序设计 10.1 手机手电筒 10.2 GPS轨迹记录器 10.3 女性贴身看护 10.4 手机QR Code二维条形码...

    Google Android SDK开发范例大全(第3版) 4/5

    9.9 随身翻译机 9.10 通过YouTube ID调用YouTube播放影片 9.11 Google Analytics分析手机用户行为 第10章 创意Android程序设计 10.1 手机手电筒 10.2 GPS轨迹记录器 10.3 女性贴身看护 10.4 手机QR Code二维条形码...

    Google Android SDK开发范例大全(第3版) 3/5

    9.9 随身翻译机 9.10 通过YouTube ID调用YouTube播放影片 9.11 Google Analytics分析手机用户行为 第10章 创意Android程序设计 10.1 手机手电筒 10.2 GPS轨迹记录器 10.3 女性贴身看护 10.4 手机QR Code二维条形码...

Global site tag (gtag.js) - Google Analytics