了解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. NET MVC RazorEngine 解析模板生成静态页

    ASP.NET MVC 解析模板生成静态页一(RazorEngine) 简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是 ...

  2. 部署到Linux使用VS Code 开发.NET Core 应用程序

    使用VS Code 开发.NET Core 应用程序 部署到Linux 跨平台 使用VS Code 开发.NET Core 应用程序 部署到Linux 跨平台. 前面讲解了VSCode开发调试 .NE ...

  3. Modular Fibonacci

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30506#problem/U fib数列对2^m取模的循环节为3*(2^(m-1)) #i ...

  4. WebService-03-使用CXF开发服务端和客户端

    写在前面的话 前面两节说了使用Java提供的包开发服务端和客户端,现在使用CXF来开发,CXF提供了两个类发而服务,一个是ServerFactoryBean,另一个是JaxWsServerFactor ...

  5. 关于JAVA Project.waitfor()死锁问题

    在正常情况下我们可以用Project.waitfor()的返回值是否等于0的方法来判断java调用外部程序是Pass或者是Fail. 但是这个方法往往会被因进程堵塞而导致程序发生死锁,无法再继续执行外 ...

  6. The Official Preppy Handbook

    The Official Preppy Handbook: Lisa Birnbach: 9780894801402: Amazon.com: Books The Official Preppy Ha ...

  7. TypeError: Cannot read property &#39;style&#39; of null 错误解决

    错误信息例如以下: JSP代码例如以下: <c:if test ="${not empty excelErrors}"> <div id="excelE ...

  8. 吐槽CSDN编辑

    Perface 近期喜欢上了markdown.我认为它就是一些HTML标签的快捷键,用一些符号来取代标签,易学易读易用,何乐而不为呢?近期也喜欢用印象笔记来让我的记忆永存,确实它强大的收集能力让我迷上 ...

  9. 30第二建筑Github Page

    从我原来博客的前端传输.链接:http://www.hacke2.cn/create-github-page/ 假设中国每一个程序猿都写博客,那么中国IT届的春天就来了 有同学问我的站点是怎么创建的, ...

  10. Date和String类型的相互转换

    String转Date: SimpleDateFormat bartDateFormat = new SimpleDateFormat("MM-dd-yyyy"); String ...