了解LoaderManager

这篇文章将介绍LoaderManager类,这是该系列的第二篇文章。
二:了解LoaderManager

注意:
要了解这一LoaderManager这部分知识,要求对Loaders怎样工作有基本了解。Loaders的实现将在下一篇文章中涵盖。如今你仅仅须要将Loaders看成一个简单、字包括的对象。该对象特性包括:1.在一个单独线程加载数据;2.监測底层数据源,当探測到有改变时就更新或者又一次查询。了解上面的Loader相关内容就足以了解本文内容了。下文全部的Loaders如果100%正确。

LoaderManager是什么?


简单的理解是,LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象。每一个Activity或者Fragment都有唯一的一个LoaderManager实例,用来启动、停止、保持、重新启动、关闭它的Loaders。这些事件有时直接在client通过调用initLoader()/restartLoader()/destroyLoader()函数来实现。通常这些事件通过基本的Activity/Fragment声明周期事件来触发,而不是手动(当然也能够手动调用)。比方,当一个Activity关闭时(destroyed),改活动将指示它的LoaderManager来销毁而且关闭它的Loaders(当然也会销毁并关闭与这些Loaders关联的资源,比方Cursor)。
LoaderManager并不知道数据怎样装载以及何时须要装载。相反地,LoaderManager仅仅须要控制它的Loaders们開始、停止、重置他们的Load行为,在配置变换(比方横竖屏切换)时保持loaders们的状态,并提供一个简单的接口来获取load结果到client中。从上面的行为能够看到,LoaderManager是一个比方今过时的startManagingCursor方法更加智能和通用的方法。在Activity的声明周期状态轮转中,比較两种管理数据的方法,能够发现LoaderManager方法有以下几个方面更胜一筹:

1. startManagingCursor管理Cursors,而LoaderManager管理Loader<D>对象。Loader<D>是一个模板类,D是一个包括了须要加载数据的类。也就是说,数据源并不必须是Cursor,它能够是List、JSONArray。。。不论什么类。LoaderManager与它包括的数据内容解耦了,所以更加灵活。

2. 调用startManagingCursor会导致Activity在已经增加管理的Cursor上调用requery()方法。在第一篇文章中提到过,在UI线程运行requery()方法代价很高。相反的是,Loader<D>的子类会异步加载(译者注:另外再开一个线程,就叫异步了。)数据,所以使用LoaderManager永远不会产生堵塞UI线程的情况。

3. startManagingCursor在配置变化(比如横竖屏切换)时,并不会保持Cursor的状态。麻烦的是,每次Activity因为配置变化(比方,简单的横竖屏切换),都会导致Cursor下回而且被又一次查询。LoaderManager就智能多了,当配置变化时,它会保持它里面的Loader们的状态,所以并不须要又一次查询数据。

4. LoaderManager提供无缝的数据监測。不论什么时候,当Loader的数据源改变,LoaderManager将会从相应的Loader上面接收到一个新的同步加载数据,并将更新数据返回给client(注意:仅当Loader被正确实现,LoaderManager才会接收到这些数据变化通知。我们将会在该系列的第三篇文章讨论自己定义Loaders的实现)。

假设你认为上面非常难,我也并不会强调她。上面的内容最重要的是LoaderManager让你的生活更easy。LoaderManager为你初始化、管理、销毁Loaders,降低了代码复杂度和与Activity或者Fragment生命周期相关的bug。很多其它地,与LoaderManager交互须要实现三个简单的回调方法,我们在下一节将讨论LoaderManager.LoaderCallbacks<D>。

实现LoaderManager.LoaderCallbacks<D>接口

LoaderManager.LoaderCallbacks<D>接口LoaderManager用来向客户返回数据的方式。每一个Loader都有自己的回调对象供与LoaderManager进行交互。该回调对象在实现LoaderManager中地位非常高,告诉LoaderManager怎样实例化Loader(onCreateLoader),以及当加载行为结束或者重新启动(onLoadFinished或者onLoadReset)之后运行什么操作。大多数情况,你须要把该接口实现为组件的一部分,比方说让你的Activity或者Fragment实现LoadManager.LoaderCallbacks<D>接口。
public class SampleActivity extends Activity implements LoaderManager.LoaderCallbacks<D> {

  public Loader<D> onCreateLoader(int id, Bundle args) { ... }

  public void onLoadFinished(Loader<D> loader, D data) { ... }

  public void onLoaderReset(Loader<D> loader) { ... }

  /* ... */
}

一旦实现该接口,client将回调对象(本例中为“this”)作为LoaderManager的initLoader函数的第三个參数传输。
总的来说,实现回调接口很直接明了。每一个回调方法都有各自明白的与LoaderManager进行交互的目的:
1. onCreateLoader是一个工厂方法,用来返回一个新的Loader。LoaderManager将会在它第一次创建Loader的时候调用该方法。
2. onLoadFinished方法将在Loader创建完成的时候自己主动调用。典型使用方法是,当加载数据完成,client(译者注:调用它的Activity之类的)须要更新应用UI。client如果每次有新数据的时候,新数据都会返回到这种方法中。记住,检測数据源是Loader的工作,Loader也会运行实际的同步加载操作。一旦Loader加载数据完成,LoaderManager将会接受到这些加载数据,而且将将结果传给回调对象的onLoadFinished方法,这样client(比方Activity或者Fragment)就能使用该数据了。

3. 最后,当Loader们的数据被重置的时候将会调用onLoadReset。该方法让你能够从就的数据中移除不再实用的数据。

在下一节中,我们将讨论Android刚開始学习的人们常常问到的问题:怎样从过时的Managed Cursor转移到更强大的LoaderManager来?

从Managed Cursor转移到LoaderManager

以下的代码跟上一篇文章的代码实现的功能类似。当然,不同就是改成使用LoaderManager来实现。CursorLoader确保全部的查询都是异步运行,这确保了我们不会堵塞UI线程。更进一步,LoaderManager在Activity全生命周期管理CursorLoader,当配置转换时保持它的数据。处理每次新数据在回调接口的onLoadFinished方法中的加载。这样Activity能够非常自由的使用查询结果。

public class SampleListActivity extends ListActivity implements
LoaderManager.LoaderCallbacks<Cursor> { private static final String[] PROJECTION = new String[] { "_id", "text_column" }; // The loader's unique id. Loader ids are specific to the Activity or
// Fragment in which they reside.
private static final int LOADER_ID = 1; // The callbacks through which we will interact with the LoaderManager.
private LoaderManager.LoaderCallbacks<Cursor> mCallbacks; // The adapter that binds our data to the ListView
private SimpleCursorAdapter mAdapter; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); String[] dataColumns = { "text_column" };
int[] viewIDs = { R.id.text_view }; // Initialize the adapter. Note that we pass a 'null' Cursor as the
// third argument. We will pass the adapter a Cursor only when the
// data has finished loading for the first time (i.e. when the
// LoaderManager delivers the data to onLoadFinished). Also note
// that we have passed the '0' flag as the last argument. This
// prevents the adapter from registering a ContentObserver for the
// Cursor (the CursorLoader will do this for us!).
mAdapter = new SimpleCursorAdapter(this, R.layout.list_item,
null, dataColumns, viewIDs, 0); // Associate the (now empty) adapter with the ListView.
setListAdapter(mAdapter); // The Activity (which implements the LoaderCallbacks<Cursor>
// interface) is the callbacks object through which we will interact
// with the LoaderManager. The LoaderManager uses this object to
// instantiate the Loader and to notify the client when data is made
// available/unavailable.
mCallbacks = this; // Initialize the Loader with id '1' and callbacks 'mCallbacks'.
// If the loader doesn't already exist, one is created. Otherwise,
// the already created Loader is reused. In either case, the
// LoaderManager will manage the Loader across the Activity/Fragment
// lifecycle, will receive any new loads once they have completed,
// and will report this new data back to the 'mCallbacks' object.
LoaderManager lm = getLoaderManager();
lm.initLoader(LOADER_ID, null, mCallbacks);
} @Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Create a new CursorLoader with the following query parameters.
return new CursorLoader(SampleListActivity.this, CONTENT_URI,
PROJECTION, null, null, null);
} @Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// A switch-case is useful when dealing with multiple Loaders/IDs
switch (loader.getId()) {
case LOADER_ID:
// The asynchronous load is complete and the data
// is now available for use. Only now can we associate
// the queried Cursor with the SimpleCursorAdapter.
mAdapter.swapCursor(cursor);
break;
}
// The listview now displays the queried data.
} @Override
public void onLoaderReset(Loader<Cursor> loader) {
// For whatever reason, the Loader's data is now unavailable.
// Remove any references to the old data by replacing it with
// a null Cursor.
mAdapter.swapCursor(null);
}
}

总结

正如其名LoaderManager,它负责在Activity或者Fragment的生命周期内管理Loader们。LoaderManager非常easy,而且它的实现代码量通常非常少。比較难的部分是实现Loaders,这个主题将在下一篇文章中讨论:实现Loaders(三)(超链接)

LoaderManager使用具体解释(二)---了解LoaderManager的更多相关文章

  1. Android 布局学习之——Layout(布局)具体解释二(常见布局和布局參数)

     [Android布局学习系列]   1.Android 布局学习之--Layout(布局)具体解释一   2.Android 布局学习之--Layout(布局)具体解释二(常见布局和布局參数)   ...

  2. {MySQL存储引擎介绍}一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用

    MySQL存储引擎介绍 MySQL之存储引擎 本节目录 一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用 一 存储引擎解释 首先确定一点,存储引擎的概念是MySQL里面才有的,不是 ...

  3. openssl之EVP系列之5---EVP_Encrypt系列函数具体解释(二)

    openssl之EVP系列之5---EVP_Encrypt系列函数详细解释(二)    ---依据openssl doc/crypto/EVP_EncryptInit.pod和doc/ssleay.t ...

  4. LoaderManager使用具体解释(三)---实现Loaders

    这篇文字将介绍Loader<D>类,而且介绍自己定义Loader的实现.这是本系列的第三篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四 ...

  5. LoaderManager使用具体解释(四)---实例:AppListLoader

    实例:AppListLoader 这篇文章将是我的第四篇,也就是最后一篇该系列的文章.请在评论里面告诉我他们是否实用.前面几篇文章的链接例如以下: 一:Loaders之前世界 二:了解LoaderMa ...

  6. LoaderManager使用具体解释(一)---没有Loader之前的世界

    来源: http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html 感谢作者Alex ...

  7. Kafka具体解释二、怎样配置Kafka集群

    Kafka集群配置比較简单,为了更好的让大家理解.在这里要分别介绍以下三种配置 单节点:一个broker的集群 单节点:多个broker的集群 多节点:多broker集群 一.单节点单broker实例 ...

  8. cocos2dx 解释二具体的启动过程:内存管理和回调

    在上一篇的第二部分中.我们有一句代码待解释的: // Draw the Scene void CCDirector::drawScene(void) { -...     //tick before ...

  9. logistic回归具体解释(二):损失函数(cost function)具体解释

    有监督学习 机器学习分为有监督学习,无监督学习,半监督学习.强化学习.对于逻辑回归来说,就是一种典型的有监督学习. 既然是有监督学习,训练集自然能够用例如以下方式表述: {(x1,y1),(x2,y2 ...

随机推荐

  1. DataReader和DataSet的区别以及使用

    DataReader和DataSet这两个对象都可以将检索的关系数据存储在内存中.它们在功能使用方面非常相似,但是它们不可以相互替换. 主要区别如表所示:   DataReader DataSet 数 ...

  2. IP Editor IP控件(对比一下封装IP控件)

    HWND hIpEdit; void __fastcall TForm2::FormCreate(TObject *Sender) { hIpEdit = CreateWindow(WC_IPADDR ...

  3. 在Windows系统上实现轻量级的线程间及进程间消息队列

    Windows没有message queue累世的IPC内核对象,使得在在处理IPC时少了一种传递消息的手段. 利用Windows的Naming Object可以实现一套简单的Inter-Thread ...

  4. 用Python对体积较大的CSV文件进行比较的经验

    用Python对体积较大的CSV文件进行比较的经验 » 进化的测试 | 进化的测试 用Python对体积较大的CSV文件进行比较的经验  python  Add comments 八 032010   ...

  5. 【错误】expected constructor, destructor, or type conversion before '.' token - 第八个游侠的日志 - 网易博客

    [错误]expected constructor, destructor, or type conversion before '.' token - 第八个游侠的日志 - 网易博客 [错误]expe ...

  6. CentOS上解压ZIP乱码的解决办法

    今天在学校做实验需要解压缩一些范例程序,我准备在我的电脑上把这个实验做完,所以就把文件copy到我的CentOS里面去了. 但是万万没想到``````解压缩的时候悲剧了,用unzip解压出来一大堆乱码 ...

  7. cocos2dX 之CCParticle

    今天我们来看看粒子特效, 何为粒子特效, 为了模拟燃烧的火焰, 天空飘下来的血环, 滴落的小雨, 这些无规律变化的物体, 我们引进了粒子特效这个名词, 粒子特效的原理是将无数的单个粒子组合使其呈现出固 ...

  8. Android---两个视图间的淡入淡出

    本文译自:http://developer.android.com/training/animation/crossfade.html 淡入淡出动画(也可以作为溶解动画)是指在渐渐的淡出一个UI组件的 ...

  9. HTML5 Canvas动画效果实现原理

    在线演示 使用HTML5画布可以帮助我们高速实现简单的动画效果.基本原理例如以下: 每隔一定时间绘制图形而且清除图形,用来模拟出一个动画过程,能够使用context.clearRect(0, 0, x ...

  10. String、StringBuffer与StringBuilder差分

    的位置不言而喻.那么他们究竟有什么优缺点,究竟什么时候该用谁呢?以下我们从以下几点说明一下 1.三者在运行速度方面的比較:StringBuilder >  StringBuffer  >  ...