安卓翻译 Activities->Loaders
来源:互联网 发布:linux如何安装软件 编辑:程序博客网 时间:2024/04/29 09:57
在安卓3.0中被介绍,loaders使在一个activity或者fragment中异步装载数据容易完成。Loaders有这些特点:
他们对每个Activity和Fragment都是可用的。
他们提供异步的数据装载。
他们管理数据源和当内容改变时传递新结果。
当一个配置改变后他们被重新创建时,他们自动重新连接左后一个loader的游标。因此,他们不需要重新查询他们的数据。
Loader API 概要
这儿有多个类和接口可能在一个应用使用loaders所涉及到的。它们用下面的表格来简要介绍:
类/接口描述LoaderManager一个与Activity或者Fragment相关联的管理一个或者多个Loader实例的抽象类。这帮助应用管理那些与Activity或者Fragment生命周期联接的长时间操作;这个大多数是和CursorLoader一起使用的,然而应用不用写它们自己的loaders来装载其它数据类型。每个activity或者fragment仅有一个LoaderManager。但是一个LoaderManager能有多个loaders。LoaderManager.LoaderCallbacks对客户端来说是一个与LoaderManager交互的回调接口。例如,你使用onCreateLoader()回调方法来创建一个新的loader。Loader执行异步数据装载的抽象类。这是对一个loader来说的基类。你可能经常使用CursorLoader,但是你能实现你自己的子类。当loaders活跃时,他们应该管理自己的数据源和当内容变化时传递新结果。AsyncTaskLoader给一个work提供一个异步任务的抽象loader。CursorLoaderAsyncTaskLoader的一个子类查询ContentResolver和返回一个Cursor。这个类以一种标准的方式实现Loader草案在查询游标,建立AsyncTaskLoader来在后台线程中执行游标查询以便它不会堵塞应用UI。使用这个loader是从一个ContentProvider中异步装载数据的最好方式,代替通过fragment或者activity的APIs中来执行一个托管查询。
在上面表格中的类和接口是在应用中你将要用来实现一个loader的最基本的组件。对每一个你创建的loader你并需要上面的所有,但是你经常需要一个对LoaderManager的引用
为了初始化一个loader和一个Loader例如CursorLoader的一个实现。下面的章节展示了你如何在应用中使用这些类和接口
在应用中使用Loaders
这个章节描述了在安卓应用中如何使用loaders。一个使用loaders的应用经常包括的有下面:
一个activity或者Fragment。
LoaderManager的一个实例。
一个CursorLoader下载被ContentProvider返回的数据。可选择的是,你能实现你自己的Loader或AsyncTaskLoader的子类来从一些其它资源下载数据。
LoaderManager.LoaderCallbacks的一个实现。这是你创建新loaders和管理你的到已经存在的loaders引用的地方。
展示loader的数据的一个方式,例如SimpleCursorAdapter。
一个数据源例如ContentProvider当使用CursorLoader。
开启一个Loader
在activity或者Fragment中LoaderManager管理一个或者更多的Loader实例。每个activity或者fragment仅有一个LoaderManager。你经常在activity的onCreate()方法中初始化一个Loader或者在fragment的onActivityCreated()方法中。你要下面这样来做:
// Prepare the loader. Either re-connect with an existing one,// or start a new one.getLoaderManager().initLoader(0, null, this);这个initLoader()有着下面的参数:
一个定义loader的独一无二的ID。在这个例子中,ID是0.
给loader提供的任意内容 at construction (在这个例子中是null)。
一个loaderManager.LoaderCallbacks实现,LoaderManager调用它来报告loader事件。在这个例子中,本地类实现了LoaderManager.LoaderCallbacks接口因此它给自己传递了一个自己的接口,this。
initLoader()调用时要确保一个loader被初始化过和活跃的。它又两个可能发生的结果:
如果被ID指定的loader已经存在,那最后被创建的loader被重用。
如果被ID指定的loader不存在,那么initLoader()出发LoaderManager.LoaderCallbacks的方法onCreateLoader()。这里也是你使代码生效来实例化和返回一个新的loader的地方。更多讨论,观看章节onCreateLoader。
在任意一个例子中给出的LoaderManager.LoaderCallbacks实现与loader相关联,并且当loader状态改变时将会被调用。如果在调用的这个时间内调用者正在它的启动状态,而且被请求的loader已经存在并且声称了它的数据,那么系统直接调用onLoadFinished()(在initLoader()过程中)因此你必须为这个的发生来做准备。
注意initLoader()方法返回被创建的Loader但是你不需要捕获一个对它的引用。LoaderManager自动管理loader的生命。LoaderManager在需要时启动和停止装载,并且维护loader的状态和它相关联的内容。这就意味着,你很少与loaders直接交互(尽管对一个使用loader方法来调整loader的行为的的例子,但是请看LoaderThrottle样例)。当特殊事件发生时,你通常都用LoaderManager.LOaderCallbacks方法来干涉装载进程。关于这节的更多讨论内容,请看使用LoaderManager Callbacks。
重启一个Loader
当你像上面展示的那样来使用initLoa(),它会使用一个被指定了ID的已经存在的loader,如果这里有的话。如果没有,它就会自己创建一个出来。但是有时你想丢弃老数据,并且重新开始。
可以使用restartLoader()来丢弃旧数据。例如,SearchView.OnQueryTextListener的实现重启了loader当用户的查询改变时。loader需要被重启,以便它能用改进的搜索过滤器来做新的查询:
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;}使用LoaderManager 回调
LoaderManager.LoaderCallbacks 是一个让客户端与LoaderManager交互的回调接口。
Loader,尤其是CursorLoader,都会在被停止后保存它们的数据。这允许应用保留它们的数据,在activity或者fragment的onStop()和onSta()方法中,以便当用户返回应用时,他们不需要等待数据重新加载。当你知道在什么时候创建一个新的loader时,使用LoaderManager.LoaderCallbacks方法,并且当是时候停止使用loader数据时告诉应用。
LoaderManager.LoaderCallbacks包括下面这些方法:
onCreateLoader() -- 对给定的ID初始化并返回一个新Loader。
onLoadFinished() --- 当前一个被创建的loader完成了它的装载之后被调用
onLoaderReset() --- 当前一个被创建的loader正在被重置时被调用,因此使它的数据不可用。
这些方法在接下来的章节中会被详细讨论
onCreateLoader
当你尝试获取一个loader(例如,通过initLoad())时,它会检查被ID指定的loader是否已经存在。如果它没有的话,它会触发LoaderManager.LoaderCallbacks方法中的onCreateLoader()。这是你创建新的loader的方法。通常情况下,这回事CursorLoader,但是你能实现你自己的Loaderz子类。
在这个例子中,onCreateLoader()回调函数创建了一个CursorLoader。你必须使用它的构造方法来建立CursorLoader,这个构造函数请求被需要用来对ContentProvider执行一次查询的完整信息集合。特别指出的是,它需要:
uri --- 提取内容的URI
projection -- 列返回的一个列表。传递null将会返回所有列,这样是没有效率的。
selection -- 一个声明哪一列被返回的过滤器,它被像一个SQL WHERE子句一样被格式化(不包括WHERE本身)。传递null将会返回被给出的URI的所有行。
selectionArgs --- 你可能在选择集合中包括?,这会被从selectionArgs的值所代替,为了它们出现在selection中。值会像Strings一样被捆绑。
sortOrder -- 怎样排序行,这被像一个SQL ORDER BY 子句一样被格式化(不包括ORDER BY本身)。传递null会使用默认排序,这可能会是无序的。
例如
// 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. 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");}onLoadFinished
当前一个被创建的loader完成了它的装载时这个方法会被调用。这个方法在被提供个这个loader的最后的数据被释放之前肯定会被调用。在这时,你应该移走所有的旧数据(在它被释放不久),但是你不在应该来做你自己对数据的释放,由于它的loader还拥有它并且小心照顾它。
loader将会释放数据一旦它知道应用不再使用它时。例如,如果数据时从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
当以前被创建的loader被重置时,这个方法被调用,因此使它的数据不可用。这个方法使你发现数据何时将会被释放,因此你就能移除对它的引用。
这个实现调用带有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. mAdapter.swapCursor(null);}
例子
作为一个例子,这是一个fragment的完整实现来呈现一个包含对通讯录content provider的一次查询结果的ListView。它用CursorLoader来管理在provider的查询。
对一个获取用户的通讯录的应用而言,就如在例子中展示的那样,你的manifest文件必须包括权限 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. 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); }}更多例子
在ApiDemos中还有一些其它的例子来展示怎样使用loaders:
LoaderCursor -- 上面展示片段的完整版本。
loaderThrottle --- 一个怎样使用节流器来减少当一个content provider的数据改变时它所查找的次数的例子。
- 安卓翻译 Activities->Loaders
- 安卓翻译(一)Activities—Fragments
- 安卓翻译(二)Activities—Fragments
- Framework Topics:Activities:Loaders
- 【安卓】如何使用Loaders
- 安卓入门--Loaders异步加载数据
- 【Android API指南】App组件(4) - Activities(2) - Loaders
- Android API Guides 之 App Components(5) - Activities - Loaders
- 安卓学习140501:组件——Activities与Intents
- Android文档翻译之loaders
- Android官网Activities文档翻译
- 安卓学习笔记(四):加载器Loaders 跟着API指南来学习
- Loaders
- Loaders
- Loaders
- Loaders
- Loaders
- Loaders
- Main函数参数argc,argv说明
- Matlab神经网络预测
- 使用linux文件句柄恢复误删除的Oracle数据文件
- smba软件
- 小世界网络的集体动力学
- 安卓翻译 Activities->Loaders
- 研究 flex 4 开发后台管理项目(1)
- sql查询20到30条记录
- 百雀羚旗舰店_店铺代码优化
- 几中基础的排序
- vc做的供其他语言调用的dll的例子 (传递的是字符串格式的参数)
- ksh
- 大家推荐本电子商务方面经典的书,最好带技术层面分析的。
- ACM各种模版整理