Android Studio教程09-加载器Loader的使用

1.加载器特征

  • 用于每个 ActivityFragment
  • 支持异步加载数据。
  • 监控其数据源并在内容变化时传递新结果。

2. Loader API

Android Studio教程09-加载器Loader的使用

3. 在应用中使用Loader

主要步骤

  1. ActivityFragment
  2. LoaderManager 的实例
  3. 一个 CursorLoader,用于加载由 ContentProvider 支持的数据。您也可以实现自己的 Loader AsyncTaskLoader 子类,从其他源中加载数据。
  4. 一个 LoaderManager.LoaderCallbacks 实现。您可以使用它来创建新加载器,并管理对现有加载器的引用。
  5. 一种显示加载器数据的方法,如 SimpleCursorAdapter
  6. 使用 CursorLoader 时的数据源,如 ContentProvider

3.1. 启动加载器

ActivityonCreate() 方法或片段的onActivityCreated() 方法内初始化 Loader

// Prepare the loader.  Either re-connect with an existing one,
// or start a new one.
// 标识ID + 构建时给加载器的可选参数 + LoaderManager.LoaderCallbacks 实现
getLoaderManager().initLoader(0, null, this);
// 如果 ID 指定的加载器已存在,则将重复使用上次创建的加载器。
// 如果 ID 指定的加载器不存在,则 initLoader() 将触发 LoaderManager.LoaderCallbacks 方法 onCreateLoader()

3.2. 重启加载器

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;
}

3.3. 使用LoaderManager回调

LoaderManager.LoaderCallbacks 是一个支持客户端与 LoaderManager 交互的回调接口。

  • 加载器(特别是 CursorLoader)在停止运行后,仍需保留其数据。这样,应用即可保留 Activity 或片段的 onStop() onStart() 方法中的数据。当用户返回应用时,无需等待它重新加载这些数据。您可使用 LoaderManager.LoaderCallbacks 方法了解何时创建新加载器,并告知应用何时停止使用加载器的数据。
  • LoaderManager.LoaderCallbacks 包括以下方法:
    • onCreateLoader():针对指定的 ID 进行实例化并返回新的 Loader
    • onLoadFinished() :将在先前创建的加载器完成加载时调用
    • onLoaderReset():将在先前创建的加载器重置且其数据因此不可用时调用

4. 实例: 访问用户联系人


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.
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.
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.
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.
mAdapter.swapCursor(null);
}
}
上一篇:html5权威指南:表格元素


下一篇:【JAVA中String、StringBuffer、StringBuilder类的使用】