本文主要从Loader入手, 去分析Loader使用、Loader的源码分析等,主要分为以下四篇:

  • 1、Loader的用法详解
  • 2、Activity对LoaderManager的管理
  • 3、LoaderManager对Loader的管理
  • 4、CursorLoader的使用

本文基于原生的 Android8.0源码进行分析。

产生背景

在Android3.0之前,很多应用程序响应性能方面有缺陷。UI切换之间的小故障、activity切换延迟、ANR问题。响应性能方面的故障大多数来源于此事实—-大多数开发者在UI线程中执行了耗时操作,其中很常用的一个就是通过网络或者本地数据库进行数据加载,用这种方式载入数据是很差的选择。

比如,在Loaders之前,cursors主要通过两个Activity方法(现在已经过时deprecated)来进行管理和查询:
public void startManagingCursor(Cursor)
public Cursor managedQuery(Uri, String, String, String, String)

由于API本身的这种设计,也会给开发者一种误导:我应该在这里进行cursor查询操作。有经验的开发者都知道在这里进行异步操作,比如自己控制子线程或者AsyncTask,处理完了通过Handler回调给主线程,但是把这些交给开发者去做,开发者去管理这些也会比较费事费力,于是Google在Android3.0引入了Loader和LoaderManager类来简化该过程。

Loaders确保所有的cursor操作是异步的,从而排除了UI线程中堵塞的可能性。而且,通过LoaderManager来管理,Loaders还可以在activity实例中保持当前的cursor数据,也就是不需要重新查询(比如,当因为横竖屏切换需要重新启动activity时)。另外,当数据改变时,Loaders可以自动检测底层数据的更新和重新检索。

Loader的简单使用

Loader 机制的 使用场景 有:

  • 加载联系人

  • 加载短信

  • 网络加载数据

    我们主要讲对于本地资源的加载,也就是访问本地数据库,获取cursor。我们先来看一下Loader的使用,主要分为两步:

  • 1、创建自己的Loader

  • 2、实现在Activity或者Fragment上LoaderCallbacks接口

    下面将通过一个demo来具体介绍Loader的使用, 不过为了节省篇幅,只贴出了代码主干部分, 完全的demo请参考文末的地址。

1、 创建自己的Loader

Google已经封装得很好了,使用Loader通常都是继承自AsyncTaskLoader或者它的子类, 如CursorLoader就是AsyncTaskLoader的子类,源码中使用CursorLoader及其子类比较多。 下面看一个简单的例子及必须实现的方法:

public class AppListLoader extends AsyncTaskLoader<List<AppEntry>> {……@Overridepublic List<AppEntry> loadInBackground() {//省略具体的代码//最核心的方法,也是必须实现的方法
//此处用来去真正加载数据, 数据加载完成后返回数据//数据最终会回调给 回调接口的onLoadFinished 方法……List<AppEntry> entries = new ArrayList<AppEntry>(apps.size());……//返回我们的数据泛型的类型return entries;}@Overridepublic void deliverResult(List<AppEntry> apps) {//此方法可不实现,但是如果实现了此方法,则必须调用super. deliverResult//正常流程都需要调用父类的deliverResult, 此方法用来分发数据
//把loadInBackground加载完的数据回调到onLoadFinished方法中
super.deliverResult(apps);
}/*** 子类必须实现的方法, 启动Loader调用*/@Overrideprotected void onStartLoading() {if (mApps != null) {deliverResult(mApps);}//如果想监听数据源, 可以再开始加载数据前,去设置一个数据监听,当数据源变化, 就回调给自己设置的监听if (mAppsObserver == null) {mAppsObserver = new InstalledAppsObserver(this);}if (takeContentChanged()) {//如果想真正开始加载数据, 则必须调用forceLoad()方法forceLoad();} else if (mApps == null) {forceLoad();}}@Overrideprotected void onStopLoading() {// The Loader has been put in a stopped state, so we should attempt to// cancel the current load (if there is one).cancelLoad();// Note that we leave the observer as is; Loaders in a stopped state// should still monitor the data source for changes so that the Loader// will know to force a new load if it is ever started again.}/*** 重置 Loader*/@Overrideprotected void onReset() {// Ensure the loader is stopped.onStopLoading();// At this point we can release the resources associated with 'apps'.if (mApps != null) {releaseResources(mApps);mApps = null;}// The Loader is being reset, so we should stop monitoring for changes.if (mAppsObserver != null) {getContext().unregisterReceiver(mAppsObserver);mAppsObserver = null;}if (mLocaleObserver != null) {getContext().unregisterReceiver(mLocaleObserver);mLocaleObserver = null;}}@Overridepublic void onCanceled(List<AppEntry> apps) { super.onCanceled(apps);// The load has been canceled, so we should release the resources// associated with 'mApps'.releaseResources(apps);}/*** 可以不用实现,父类通过此方法去加载数据,* 内部会调用 loadInBackground()*/@Overridepublic void forceLoad() {super.forceLoad();}……
}

2、在Activity或者Fragment中实现LoaderCallbacks回调接口

LoaderCallbacks接口主要有三个方法, 实现如下:

public class LoaderDemoFragment extends ListFragment implementsLoaderManager.LoaderCallbacks<List<AppEntry>> {@Overridepublic Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) {//这个方法主要用来创建我们需要的Loader//在这里我们还可以做一些想做的事return new AppListLoader(getActivity());}@Overridepublic void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) {//数据加载完毕会回调到这个方法, mAdapter.setData(data);if (isResumed()) {setListShown(true);} else {setListShownNoAnimation(true);}}@Overridepublic void onLoaderReset(Loader<List<AppEntry>> loader) {//该方法将在 先前创建的加载器重置 且 数据因此不可用 时调用,
//通过此回调我们可以了解何时将释放数据,因此能够及时移除其引用。mAdapter.setData(null);}/*** 找一个合适的地方, 初始化Loader*/
@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState); // 参数:id ,唯一标识, Bundle,额外的数据, LoaderCallbacks接口getLoaderManager().initLoader(LOADER_ID, null, this);}
}

Loader的使用流程大致就是这样,详细的代码可以去这个地址下载demo:demo下载

后面讲继续分析Loader的源码部分,了解Loader实现原理。

Loader的用法详解相关推荐

  1. python argv 详解_Python3 sys.argv[ ]用法详解

    sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个"外部"很关键,因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可 ...

  2. oracle中的exists 和 not exists 用法详解

    from:http://blog.sina.com.cn/s/blog_601d1ce30100cyrb.html oracle中的exists 和 not exists 用法详解 (2009-05- ...

  3. ROW_NUMBER() OVER()函数用法详解 (分组排序 例子多)

    ROW_NUMBER() OVER()函数用法详解 (分组排序 例子多) https://blog.csdn.net/qq_25221835/article/details/82762416 post ...

  4. python的继承用法_【后端开发】python中继承有什么用法?python继承的用法详解

    本篇文章给大家带来的内容是关于python中继承有什么用法?python继承的用法详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 面向对象三大特征 1.封装:根据职责将属性和方法 ...

  5. C++中substr()函数用法详解

    C++中substr()函数用法详解 原型: string substr (size_t pos = 0, size_t len = npos) const; 返回一个新构造的string对象,其值初 ...

  6. php theme_path,PHP_Yii2主题(Theme)用法详解,本文实例讲述了Yii2主题(Theme) - phpStudy

    Yii2主题(Theme)用法详解 本文实例讲述了Yii2主题(Theme)用法.分享给大家供大家参考,具体如下: 首先看看主要的配置方式: 'components' => [ 'view' = ...

  7. LayoutInflater的inflate函数用法详解

    LayoutInflater的inflate函数用法详解 LayoutInflater作用是将layout的xml布局文件实例化为View类对象. 获取LayoutInflater的方法有如下三种: ...

  8. Ext.Net学习笔记22:Ext.Net Tree 用法详解

    上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat="server"><Root> ...

  9. WinDbg用法详解

    WinDbg用法详解 对WinDbg的方方面面作了详细的讲解. 转载于:https://blog.51cto.com/laokaddk/125111

最新文章

  1. C# 参考之访问关键字:base、this
  2. 【Ubuntu】安装Java和Eclipse
  3. 查重多少合格_期刊论文查重一般多少合格?
  4. codeforces-984D——XOR-pyramid(DP)
  5. Pytorch---训练与测试时爆显存(out of memory)的一个解决方案(torch.cuda.empty_cache())
  6. c++ 怎么输出保留2位小数的浮点数
  7. 微博评论数据爬取思路及代码分享
  8. CS143 6、7. 自顶向下和自底向上的语法分析
  9. 可编程数据平面(论文阅读)
  10. 企业内网安全体系化发展方向
  11. thinkphp6 JWT
  12. 火狐下载 firefox免费高速下载 firefox又出新版本了
  13. 小葫芦直播管家找不到服务器,小葫芦直播管家-开播版,直播插件手动安装教程...
  14. Flutter中那些你需要知道的文本知识!
  15. 系统分析与设计HW4
  16. 施密特触发器基础知识
  17. 商城API开发之下单接口
  18. 搬水果 在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过
  19. 单片机应用技术c语言版考试答案,单片机应用技术(C语言)试题
  20. 用CSS制作凸出按钮效果

热门文章

  1. 如何在Apache官网下载Apache服务器 安装包
  2. 用Go语言 模拟银行存款,取款,查询等操作 (Golang经典编程案例)
  3. linux查看java线程死锁_ccriticalsection 多线程 死锁_c++ 线程死锁_linux 线程 死锁
  4. 高可用性架构:云计算和高可用性
  5. OPNET新建WLAN信道模型的方式
  6. 英巴卡迪诺中国发布官方视频专栏
  7. Java并发编程78讲--29 第29讲:HahMap 为什么是线程不安全的?
  8. 转载 - 5个在线的网站测试和验证工具
  9. 游戏数据逆向分析系列课程之64位篇
  10. 劳易测测距传感器ODS9L2.8/LAK-650-M12