Android异步处理之AsyncTaskLoader简单使用
简介
不管是在Android应用开发还是Android平台开发中,异步处理通常是最基本的coding要求。如果你还在主线程中写一些数据库,网络请求,读写本地文件等操作的话那说明你还不是一个合格的Android程序员。
通常情况下我们使用的最多的Android异步处理方法是AsyncTask
和Handler
,但今天要给大家带来的是大家不常使用的AsyncTaskLoader
的使用方法。
AsyncTaskLoader
从名字看出来它似乎和AsyncTask
有关系,看一下Google官方是怎么给AsyncTaskLoader
下定义的:
Abstract Loader that provides an AsyncTask to do the work
果然是样,AsyncTaskLoader
是使用一个AsyncTask
来进行异步处理的。那么问题来了,既然都有了AsyncTask
了为什么还要搞出来一个AsyncTaskLoader
呢?
其实AsyncTaskLoader
远没有大家想的那么简单。说的通俗一点,如果把AsyncTask
比作一台烤面包机的话,那么AsyncTaskLoader
就是操作烤面包机的面包师。AsyncTask
如同烤面包机接受命令完成面包的烤制任务,一旦任务完成它就停止了工作。然而AsyncTaskLoader
如同面包师一样要根据顾客的需求来使用烤面包机。顾客会不停的光顾,那么面包师就会不停的使用烤面包机烤面包。
具体事例
下面我们就通过烤面包机和面包师的例子来演示一下AsyncTaskLoader
的使用方法。
首先肯定少不了面包师(Baker):
package com.example.asyncloaderdemo;
import java.util.ArrayList;
import java.util.List;
import android.content.AsyncTaskLoader;
import android.content.Context;
public class Baker extends AsyncTaskLoader<List<Bread>> {
// 用于查询当前需要多少个面包
BakeryCallback mCallback;
//面包房回调,用于获得当面面包需求量
interface BakeryCallback {
int getNeededBreads();
}
public Baker(Context context, BakeryCallback callback) {
super(context);
mCallback = callback;
}
@Override
public List<Bread> loadInBackground() {
List<Bread> breads = new ArrayList<Bread>();
//获得当前需要做的面包
int needs = mCallback.getNeededBreads();
for (int i = 0; i < needs; i++) {
//制作面包,耗时操作
breads.add(new Bread());
}
//面包制作完成
return breads;
}
@Override
public void deliverResult(List<Bread> data) {
super.deliverResult(data);
}
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
}
}
面包师有了,面包房(Bakery)也不能少
package com.example.asyncloaderdemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class Bakery extends BroadcastReceiver {
final Baker mBaker;
public static String CUSTOMER_ACTION = "com.example.asyncloaderdemo.new_customer" ;
public Bakery(Baker baker) {
mBaker = baker;
IntentFilter filter = new IntentFilter(CUSTOMER_ACTION);
baker.getContext().registerReceiver(this, filter);
}
@Override public void onReceive(Context context, Intent intent) {
//通知面包师来客人了,要做面包了。
mBaker.onContentChanged();
}
}
面包房和面包师都有了,还缺一个场景(MainActivity)
package com.example.asyncloaderdemo;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.example.asyncloaderdemo.Baker.BakeryCallback;
import android.support.v7.app.ActionBarActivity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Intent;
import android.content.Loader;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends ActionBarActivity {
private LoaderCallbacks<List<Bread>> mCallbacks;
//面包房
private Bakery mBakery;
//面包师
private Baker mBaker;
//面包需求量
private int mNeededBreads;
//唯一标识
private final int mLoaderId = 42;
private BakeryCallback mBreadCallback = new BakeryCallback() {
@Override
public int getNeededBreads() {
return mNeededBreads;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNeededBreads = 0;
mBaker = new Baker(this, mBreadCallback);
mBakery = new Bakery(mBaker);
mCallbacks = new LoaderCallbacks<List<Bread>>() {
@Override
public Loader<List<Bread>> onCreateLoader(int id, Bundle args) {
if (mBaker == null) {
mBaker = new Baker(MainActivity.this, mBreadCallback);
}
return mBaker;
}
@Override
public void onLoadFinished(Loader<List<Bread>> loader, List<Bread> data) {
mNeededBreads = 0 ;
//面包师完成面包烤制
Log.d("scott", "sell " + data.size() + " breads") ;
}
@Override
public void onLoaderReset(Loader<List<Bread>> loader) {
}
};
//面包师开始工作
getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
//顾客开始上门
mockCustomer();
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBakery);
}
//模拟源源不断的顾客需求
private void mockCustomer(){
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
Thread.sleep(3000);
Random random = new Random();
mNeededBreads =random.nextInt(10);
Intent intent = new Intent(Bakery.CUSTOMER_ACTION);
sendBroadcast(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
接下来我们来看一下程序运行结果:
通过上图并结合代码可以看出来每隔三秒就会有新的顾客上门,顾客上门后面包房通知面包师需要做面吧哦了,接着面包师就会在后台不停的开始使用面包机(AsyncTask)做面包。
总结
说到这里可能有些同学有疑问了,我怎么从头到尾都没有开到AsyncTask
的影子呢?你当然看不到,这就是AsyncTaskLoader
设计精妙之处,它做到了让你唯一需要考虑的就是烤面包(异步处理)这个事物逻辑,而不需要考虑异步处理本身的实现上。同时这也充分体现了设计模式中的单一职责
和最少知道
原则。
使用场景
AsyncTaskLoader
一般使用在数据源处于不断更新并且请求刷新数据源是个耗时操作的情况下还需要UI去同步更新相关数据的场景(这句话怎么这么拗口)。
Android异步处理之AsyncTaskLoader简单使用的更多相关文章
- [Android Pro] Android异步任务处理之AsyncTaskLoader的使用
reference to : http://blog.csdn.net/happy_horse/article/details/51518280 最近项目中涉及到加载本地的地名.db文件,数据量大,自 ...
- Android异步回调中的UI同步性问题
Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...
- 演化理解 Android 异步加载图片
原文:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html#3018499 在学习"Android异步加载图像小结&q ...
- Android异步载入全解析之使用多线程
异步载入之使用多线程 初次尝试 异步.异步,事实上说白了就是多任务处理.也就是多线程执行.多线程那就会有各种问题,我们一步步来看.首先.我们创建一个class--ImageLoaderWithoutC ...
- Android 异步消息处理机制前篇(二):深入理解Message消息池
版权声明:本文出自汪磊的博客,转载请务必注明出处. 上一篇中共同探讨了ThreadLocal,这篇我们一起看下常提到的Message消息池到底是怎么回事,废话少说吧,进入正题. 对于稍有经验的开发人员 ...
- Android 异步消息处理机制终结篇 :深入理解 Looper、Handler、Message、MessageQueue四者关系
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 我们知道更新UI操作我们需要在UI线程中操作,如果在子线程中更新UI会发生异常可能导致崩溃,但是在UI线程中进行耗时操作又会导致ANR,这 ...
- Android异步处理系列文章四篇之二 使用AsyncTask异步更新UI界面
Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ...
- Android异步下载
概述 实现App常见下载公共 支持通知栏显示 支持 暂停.取消功能,使用Service.AsyncTask实现异步下载.特点简单.实用.方便源码扩展修改 详细 代码下载:http://www.demo ...
- Android异步载入全解析之大图处理
Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图 ...
随机推荐
- 设置mvc路由映射
routes.MapRoute( "chapter", "{action}/{bookId}/{pageindex}", new { controller = ...
- PHP 抽象类的使用
//抽象类就是一个模版 abstract class db{ /* 参数:sql语句 返回值:索引的数组 */ abstract public function test($str); //没有方法体 ...
- Java分布式 一些概念理解
转至 java那些事 2017-02-09 有些朋友工作一年了觉得该深入一下子了,所以想深入学习一下以提升自己的专业技能,想问一下如何入门Java分布式应用,学习过程大致是怎么样的,涉及到那些知识, ...
- linux一条命令添加一个root级别账户并设置密码
内网机器提权添加账户,无回显,设置密码就不好弄,下面就是添加一个root级别的账户并设置密码的命令 ? 1 useradd -p `openssl passwd -1 -salt 'lsof' a ...
- 使用 P3P 规范让 IE 跨域接受第三方 cookie
前两天帮同事处理一个 js 跨域问题,使用 jsonp 跨域提交用户名密码请求,实现自动登录第三方网站,即 SSO(single-sign-on) 单点登录,一处登录处处登录.在 Chrome 下没问 ...
- Hadoop-2.4.0分布式安装手冊
文件夹 文件夹 1 1. 前言 2 2. 部署 2 2.1. 机器列表 2 2.2. 主机名 2 2.2.1. 暂时改动主机名 3 2.2.2. 永久改动主机名 3 2.3. 免password登录范 ...
- 利用dd命令制作u盘iso镜像
现在安装系统都是用u盘安装,那么制作u盘的iso镜像就是必须的了.现在此类工具倒是不少,但是,好用的不多,有的还收费.唉,还是用dd吧,老配方,老味道. 首先:要df -h一下,看看u盘的盘符,类似 ...
- Atitit.vod 视频播放系统 影吧系统的架构图 架构体系 解决方案
Atitit.vod 视频播放系统 影吧系统的架构图 架构体系 解决方案 1. 运行平台:跨平台 android ios pc mobile 1.1. -------------前端 界面------ ...
- 新标准C++程序设计读书笔记_类和对象
面向对象的程序设计方法 抽象:将某类客观事物共同特点(属性)归纳出来,形成一个数据结构(可以用多个变量描述事物的属性):将这类事物所能进行的行为也归纳出来,形成一个个函数,这些函数可以用来操作数据结构 ...
- Unity中使用ulua的个人经验总结
热度 286052 2015-3-15 14:32 |个人分类:技术类| Lua Lua代码都是运行时才编译的,不运行的时候就如同一张图片.一段音频一样,都是文件:所以更新逻辑只需要更新脚本,不需要再 ...