简介

不管是在Android应用开发还是Android平台开发中,异步处理通常是最基本的coding要求。如果你还在主线程中写一些数据库,网络请求,读写本地文件等操作的话那说明你还不是一个合格的Android程序员。

通常情况下我们使用的最多的Android异步处理方法是AsyncTaskHandler,但今天要给大家带来的是大家不常使用的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简单使用的更多相关文章

  1. [Android Pro] Android异步任务处理之AsyncTaskLoader的使用

    reference to : http://blog.csdn.net/happy_horse/article/details/51518280 最近项目中涉及到加载本地的地名.db文件,数据量大,自 ...

  2. Android异步回调中的UI同步性问题

    Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...

  3. 演化理解 Android 异步加载图片

    原文:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html#3018499 在学习"Android异步加载图像小结&q ...

  4. Android异步载入全解析之使用多线程

    异步载入之使用多线程 初次尝试 异步.异步,事实上说白了就是多任务处理.也就是多线程执行.多线程那就会有各种问题,我们一步步来看.首先.我们创建一个class--ImageLoaderWithoutC ...

  5. Android 异步消息处理机制前篇(二):深入理解Message消息池

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 上一篇中共同探讨了ThreadLocal,这篇我们一起看下常提到的Message消息池到底是怎么回事,废话少说吧,进入正题. 对于稍有经验的开发人员 ...

  6. Android 异步消息处理机制终结篇 :深入理解 Looper、Handler、Message、MessageQueue四者关系

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 我们知道更新UI操作我们需要在UI线程中操作,如果在子线程中更新UI会发生异常可能导致崩溃,但是在UI线程中进行耗时操作又会导致ANR,这 ...

  7. Android异步处理系列文章四篇之二 使用AsyncTask异步更新UI界面

    Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ...

  8. Android异步下载

    概述 实现App常见下载公共 支持通知栏显示 支持 暂停.取消功能,使用Service.AsyncTask实现异步下载.特点简单.实用.方便源码扩展修改 详细 代码下载:http://www.demo ...

  9. Android异步载入全解析之大图处理

    Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图 ...

随机推荐

  1. mqtt选择

    1.名称 MQTT kafka 2.历史 IBM推出的一种针对移动终端设备的发布/预订协议. LinkedIn公司开发的分布式发布-订阅消息系统.后来,成为Apache项目的一部分. 3.原理 基于二 ...

  2. C++的泛型编程方式

    1.使用类模板创建数组 下面这段代码:是创建一个元素为 T 类型的数组. #pragma once template<class T> class MyArray { public: // ...

  3. andorid手机电脑操作

    之前一直使用androidscreencast在pc上对手机进行操作,好久都没用了,前些天再次用的时候,提演示样例如以下: 决定还是自己写一个吧,由于7月份要做一个小分享,打算讲一些android的东 ...

  4. js 时间对比

    https://www.cnblogs.com/xiangsj/p/7977325.html http://www.jb51.net/article/45560.htm isOverdue (time ...

  5. wx小程序的学习

    传送门: # 微信小程序案例大全 https://www.cnblogs.com/icyhoo/p/6282574.html # 微信小程序开发工具 https://mp.weixin.qq.com/ ...

  6. atitit.无为而治在企业管理,国家治理,教育领域的具体思想与实践

    atitit.无为而治在企业管理,国家治理,教育领域的具体思想与实践 1. 什么是无为而治 1 2. 无为而治的三个原则 1 3. 抓大放小 1 4. 治理国家 2 5. 企业管理 2 6. 教育领域 ...

  7. unittest最详细的解说

    转自:http://www.imooc.com/article/257230 一.什么是unittest unittest是Python单元测试框架,类似于JUnit框架. unittest中有4个重 ...

  8. MySQL 行号(类似SQLServer的row_number())

    Select ID,(@rowNum:=@rowNum+1) as RowNo From a,(Select (@rowNum :=0) ) b

  9. ThinkPHP 模板 Volist 标签嵌套循环输出多维数组

    ThinkPHP 中对 volist 标签嵌套使用可实现多维数组的输出. volist 嵌套使用 一般的二维数组,可以用 volist 标签直接循环输出.对于多维数组,则需要对其中的数组成员再次使用 ...

  10. Using Fast Weights to Attend to the Recent Past

    Ba, Jimmy, et al. "Using Fast Weights to Attend to the Recent Past." Advances In Neural In ...