Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Content Provider Tutorial--安卓內容提供者系列5--Loader用法

Android Content Provider Tutorial--安卓內容提供者系列5--Loader用法

編輯:關於Android編程

Loaders(加載器)

What’s a Loader?(什麼是加載器)

Loaders make it easy to load data asynchronously in an activity or fragment. Loaders have these characteristics:

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.

加載器可以使在Activity或Fragment中異步加載數據變得很容易。加載器有下面這些特點:

在每個Activity 和Fragment中都可以獲取的到加載器。

他們提供數據的異步加載。

他們監視他們的數據的來源,並且在內容更改時提供新的結果。

當程序的配置更改後加載器的游標會重新創建,加載器能自動重新連接到最新的那個游標。因此,他們不需要重新查詢他們的數據。

Loaders were introduced in Honeycomb (API 11).

The Android Support Package includes support for loaders. By including the support package in your application, you can use loaders even if your application for a minSdkVersion of 4 or later.

Android 3.0(API 11)版本才推出加載器。

Android支持包包含了對加載器的支持。通過在應用程序中放入支持包,你可以即使最小版本是api4或更高版本中使用加載器。

The Loader Classes and Interfaces(加載器涉及到的類及接口)

There are several classes and interfaces that implement the loader functionality:

有下面這幾個類和接口來實現加載器的功能:

LoaderManager

An abstract class associated with an Activity or Fragment for managing one or more Loader instances. There is only one LoaderManager per activity or fragment. But a LoaderManager can have multiple loaders.

它是一個與Activity 或 Fragment關聯,用來管理一個或多個加載器實例的抽象類。Activity 或 Fragment只有一個LoaderManager。但一個LoaderManager可以有多個加載器。

LoaderManager.LoaderCallbacks

A callback interface for a client to interact with the LoaderManager.

這是客戶端用來和LoaderManager交互的一個回調接口。

Loader

An abstract class that performs asynchronous loading of data.

一個用來異步加載數據的抽象類

AsyncTaskLoader

Abstract loader class that provides an AsyncTask to do the work.

一個可以提供AsyncTask來工作的抽象loader類

CursorLoader

A concrete 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.

這是AsyncTaskLoader的一個具體子類,他查詢ContentResolver並返回一個游標。這個類以查詢游標的標准方式實現了Loader協議,他基於AsyncTaskLoader在後台線程中執行游標查詢操作,這樣它就不會阻塞應用程序的UI線程。

As of API 15, the only concrete Loader implementation is the CursorLoader, which can query only a content provider; it cannot run a query directly against a SQLite database.Android到了API 15,加載器的唯一具體實現就只有CursorLoader了,它只可以查詢ContentProvider,不能直接對SQLite數據庫進行訪問。

Using Loaders in an Application(在應用中使用加載器)

An application that uses loaders typically includes the following:

An Activity or Fragment.

An instance of the 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.

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

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

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

一個使用加載器的應用程序通常包括以下部分:

一個Activity 或者 Fragment。

LoaderManager的實例。

一個能夠加載ContentProvider提供的數據的CursorLoader。或者,你也可以自己實現一個Loader或AsyncTaskLoader的子類來加載源於其他地方的數據。

一個數據源,比如ContentProvider,當使用CursorLoader的時候。

LoaderManager.LoaderCallbacks一個實現類。這就是你創建新的加載器實例和管理現有加載器引用的地方。

一種顯示加載器的數據的方式,比如用SimpleCursorAdapter。

Accessing the LoaderManager(訪問LoaderManager)

To use loaders in an activity or fragment, you need an instance of LoaderManager.

There is only one LoaderManager per activity or fragment.在 activity 或 fragment中使用加載器,你需要一個LoaderManager實例。

每個activity 或 fragment中只有一個LoaderManager實例。

If you’re using the standard APIs, invoke getLoaderManager() as provided in the Activity and Fragment classes.

If you’re using the Support Package, you must use android.support.v4.app.FragmentActivity as the base class for your activity.

Invoke FragmentActivity.getSupportLoaderManager() to obtain a LoaderManager for the activity.

Invoke android.support.v4.app.Fragment.getLoaderManager() to obtain a LoaderManager for a fragment.

如果你使用標准的api,可以調用Activity 和 Fragment中提供 的getLoaderManager()方法來獲得LoaderManager實例。

如果你使用支持包,就必須使用android.support.v4.app.FragmentActivity作為Activity的基類。

可以調用FragmentActivity.getSupportLoaderManager()方法來為activity獲取一個LoaderManager實例。

可以調用android.support.v4.app.Fragment.getLoaderManager()方法來為Fragment獲取一個LoaderManager實例。

Starting a Loader(啟動加載器)

Invoke FragmentManager.initLoader() to initialize a specified Loader:

可以調用FragmentManager.initLoader()方法去初始化一個加載器。

// 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:

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

Optional arguments in the form of a Bundle to supply to the loader at construction (null in this example).

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.

initLoader()方法接受以下參數:

一個用來標識加載器的唯一整數ID。在這個例子中,ID為0。

還有一個bundle形式的可選參數,主要用來構造loader的(在這個例子中該參數為null)。

還要實現一個LoaderManager.LoaderCallbacks,這個是LoaderManager用來回調加載事件的。在這個例子中,本地類實現了LoaderManager.LoaderCallbacks接口,所以它給自己傳遞了一個引用。

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

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

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.

You typically initialize a Loader within an activity’s onCreate() method, or within a fragment’s onActivityCreated() method.

調用initLoader()確保了加載器的初始化和激活狀態。它有兩個可能的結果:

如果ID指定的加載器已經存在,新創造的加載器就是重用的。

如果ID指定的加載器不存在,initLoader()就會觸發LoaderManager.LoaderCallbacks中的 onCreateLoader()方法。這就是你寫代碼實例化並返回一個新的加載器的地方。

您通常會在一個Activity的onCreate()方法中初始化一個加載器,或在一個Fragment的onActivityCreated()方法中做這個事。

Restarting a Loader(重啟一個加載器)

If you want to discard the the old data returned by a Loader and have it load fresh data, invoke the FragmentManager.resetLoader() method.

如果你想丟棄掉加載器返回的舊的數據,並讓其加載新數據,那就調用FragmentManager.resetLoader()方法。

// Refresh the loader with new data

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

The resetLoader() method accepts the same arguments as initLoader():

The integer ID of a Loader

Optional arguments in the form of a Bundle

A LoaderManager.LoaderCallbacks implementation

resetLoader()方法接收的參數和initLoader()接收的一樣:

一個標識加載器的整數ID

bundle形式的可選參數

LoaderManager.LoaderCallbacks的實現

Destroying a Loader(銷毀一個加載器)

If you want to destroy a Loader and have it discard the data that it loaded, invoke the FragmentManager.destroy() method.

The destroyLoader() method accepts only the integer ID of a Loader to destroy.

如果你想銷毀一個加載器,並丟棄掉它加載的數據,那就調用FragmentManager.destroyLoader()方法。

destroyLoader()方法只接受一個參數,即加載器的整型ID。

// Destroy a loader and release its data

getLoaderManager().destroyLoader(0);

The LoaderManager.LoaderCallbacks Listener(LoaderManager.LoaderCallbacks回調監聽器)

The LoaderManager.LoaderCallbacks listener must implement the following interface:

LoaderManager.LoaderCallbacks回調監聽器必須實現以下接口:

public interface LoaderCallbacks { public Loader onCreateLoader(int id, Bundle args); public void onLoadFinished(Loader loader, DataType data); public void onLoaderReset(Loader loader); }

onCreateLoader()

The LoaderManager invokes this method if it needs to create the Loader with the specified id. The LoaderManager also passes along the Bundle argument it received in the LoaderManager.initLoader() method.

The listener must instantiate the specified loader and return a reference to it. The LoaderManager then manages interaction with the Loader as required.

LoaderManager如果需要根據指定id創建加載器,就必須調用這個方法。LoaderManager也會把在LoaderManager.initLoader()方法Bundle參數繼續傳遞。

監聽器必須實例化指定加載程序並返回一個引用。然後LoaderManager管理與裝載機的交互。

onLoadFinished()

The LoaderManager invokes this method when the loader has finished loading the requested data. It provides a reference to the data and the loader that generated it.

The listener should then use the data in whatever way the fragment or activity requires. For example, if a CursorLoader provides a Cursor as a result of a query, the onLoadFinished() method might hook up the Cursor to a CursorAdapter to display the data.

當加載器完成了對請求數據的加載,LoaderManager就會調用這個方法。它提供了一個數據的引用和一個產生該數據的加載器的引用。

然後監聽器就可以以任何Activity或Fragment想要的方式去使用這些數據。例如,如果一個CursorLoader提供一個游標作為查詢的結果,那onLoadFinished()方法會把游標鏈接到CursorAdapter,以此來顯示數據。

onLoaderReset()

The LoaderManager invokes this method when a loader is being reset or destroyed. It indicates that the data provided by the loader is becoming unavailable. At this point, the listener should remove any references it has to the loader’s data.

當加載器被重置或銷毀時,LoaderManager會調用該方法。這表示加載器提供的數據變得不再可用。在這一點上,監聽器應該刪除它所有的任何關於加載器的數據的引用。

The loader "owns" the data itprovides. The listener should not attempt to release or delete the data. For example, a CursorLoader provides a Cursor, the consumer of the Cursor should not attempt to close it; it should simply release its reference to the Cursor in response to the onLoaderReset() method call.加載器“擁有”它所提供的數據。監聽器不應試圖釋放或刪除數據。例如,CursorLoader提供了一個游標,游標的使用者不應試圖關閉它;而應該只是簡單地釋放其游標的引用,在onLoaderReset()方法被調用的時候。

The CursorLoader

The CursorLoader is a concrete loader implementation that queries the ContentResolver and returns a Cursor.

Typically, the only interaction your listener implementation needs to have with a CursorLoader is to instantiate it in response to an onCreateLoader() call.

The CursorLoader constructor take a Context followed by the same arguments as ContentResolver.query():

uri

The URI, using the content:// scheme, for the content to retrieve.

projection

A list of which columns to return. Passing null returns all columns, which is inefficient.

selection

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

selectionArgs

You may include ?s in selection, which will be replaced by the values from selectionArgs, in the order that they appear in the selection.

sortOrder

How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null use the default sort order.

CursorLoader是加載器的具體實現,它可以查詢ContentResolver並返回一個游標。

一般來說,在onCreateLoader()被調用的時候,你實現的監聽器和CursorLoader唯一需要做的交互就是實例化CursorLoader。

CursorLoader構造函數接受一個和ContentResolver.query()跟隨的一樣的上下文參數:

uri

URI,使用格式: content:/ /scheme,表示要檢索的內容。

projection

一個裝有要返回的列的集合。傳null表示要返回所有列,當然這是低效的。

selection

一個聲明哪些行可以被返回的過濾器,格式類似於一個SQL語句中的WHERE子句(不包括WHERE單詞自身)。通傳null表示要返回所有和給定URI對應的行。

selectionArgs

selection參數中包含一些篩選條件,這些條件會被selectionArgs參數中的值所替代,selectionArgs參數順序和seletion中的參數順序一一對應。

sortOrder

這個參數表示如何給返回的行排序,它的格式類似於一個SQL語言中的ORDER BY從句(不含ORDER BY這個關鍵詞本身)。如果傳null的話就使用默認的排序順序,這可能是無序的。

A Simple Example(舉個簡單例子)

public static class CursorLoaderListFragment extends ListFragment implements MenuItem.OnMenuItemClickListener, LoaderManager.LoaderCallbacks { // This is the Adapter being used to display the list's data. SimpleCursorAdapter mAdapter; @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"); // 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("Refresh"); item.setIcon(android.R.drawable.ic_menu_rotate); item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setOnMenuItemClickListener(this); } public boolean onMenuItemClick(String newText) { // Called when the user clicks the refresh button. getLoaderManager().restartLoader(0, null, this); return true; } // These are the Contacts rows that we will retrieve. static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS, }; public Loader 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. Uri baseUri = Contacts.CONTENT_URI; // Now create and return a CursorLoader that will take care of // creating a Cursor for the data being displayed. 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 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 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. mAdapter.swapCursor(null); } }

Module Summary(總結)

You should now be able to:

Write client code that can read and modify the data managed by a content provider

Implement a basic content provider to expose structured data to other applications

Use loaders to retrieve a Cursor from a content provider without blocking your application’s main thread

現在,您應該能夠:

編寫客戶端代碼,用來可以讀取和修改由ContentProvider管理的數據;

實現一個基本的ContentProvider,將結構化數據暴露給其他應用程序;

在不阻塞你的應用主線程的情況下,通過使用加載器來檢索從ContentProvider中獲取到的游標。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved