Android常用异步任务执行方法
Handler原理及基本概念
- Message 意为消息,发送到Handler进行处理的对象,携带描述信息和任意数据。
- MessageQueue 意为消息队列,Message的集合。
- Looper 有着一个很难听的中文名字,消息泵,用来从MessageQueue中抽取Message,发送给Handler进行处理。
- Handler 处理Looper抽取出来的Message。
在如下操作中都是基于UI主线程,在异步任务中使用Handler机制更新UI必须用new Handler();来初始化。
// 默认使用UI主线程的Looper
Handler mHandler = new Handler();
mHandler.post(new Runnable(){});
Thread创建与销毁
在Android开发中经常会使用到线程,一想到线程,很多同学就立即使用
new Thread(){...}.start();这样的方式。这样如果在一个Activity中多次调用上面的代码,那么将创建多个匿名线程,程序运行的越久可能会越来越慢。因此,需要一个Handler来启动一个线程,以及删除一个线程。
保证线程不会重复的创建。
使用HandlerThread和Handler配合实现异步后台任务
特点:
- 由2个Handler和1个HandlerThread来实现
- 后台线程串行执行
代码示例:
// UI线程的Handler
Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        // 处理UI更新
};
HandlerThread mBackThread = new HandlerThread("mybackthread");
mBackThread.start();
// 后台线程的Handler
Handler mBackHandler = new Handler(mBackThread.getLooper());
mBackHandler.post(new Runnable() {
    @Override
    public void run() {
        // 后台线程执行耗时操作,异步
        ...
        // mHandler发消息,回到主线程更新UI
        mHandler.sendMessage(msg);
    }
});
注意:mBackHandler的初始化必须在mBackThread.start();之后,否则拿不到这个线程的looper。
这种模式通过mBackHandler.post(new Runnable() {})来实现后台异步任务执行,所有后台任务都是通过HandlerThread这个线程执行的,但是HandlerThread是串行执行任务的,也就是每次post后进入队列排队执行。
HandlerThread的退出:
@Override
protected void onDestroy() {
    super.onDestroy();
    if(mBackThread != null){
        mBackThread.quitSafely();
        try {
            mBackThread.join();
            mBackThread = null;
            mBackHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
AsyncTask实现异步任务执行
查看源码AsyncTask只是对Thread和Handler的一个封装。
基本概念
- 3个泛型参数
 AsyncTask <Params, Progress, Result>
 Params: 指定的是我们传递给异步任务执行时的参数的类型
 Progress: 指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型
 Result: 指定的是异步任务执行完后返回给UI线程的结果的类型
 我们在定义一个类继承AsyncTask类的时候,必须指定好这三个泛型的类型,如果都不指定的话,则都将其写成Void
- 4个执行步骤
 onPreExecute():UI Thread当中执行,这个方法是在执行异步任务之前的时候执行,我们可以在异步任务执行前做UI提示
 doInBackground(Params... params):这个方法就是来处理异步任务的方法,执行耗时操作。这个方法也是必须要实现的抽象方法。
 onProgressUpdate(Progess... values):UI Thread当中执行,用来更新进度条等
 onPostExecute(Result... result):UI Thread当中执行,当异步任务执行完之后,将doInBackground结果返回给这个方法来更新UI
- 2种执行方式
 后台线程可以设置为串行或者并行执行
 串行:execute(Params... params)
 并行:executeOnExecutor(Executor exec, Params... params)
 注意:各SDK版本execute默认执行方式不统一,1.5中顺序执行,1.6到 2.3中并行执行,3.0以后又改回串行执行,并添加并行执行接口executeOnExecutor
注意事项
- 必须在UI线程中加载和创建,以及调用execute
- 不能做特别耗时的操作,建议只几秒内的异步任务
- 一个AsyncTask对象只能被执行一次,即只能调用一次execute,否则会抛出异常报错
 Caused by: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
- 不能在程序中主动调用4个步骤
代码示例
// 初始化AsyncTask及执行
protected void function() {
    ...
    // 串行执行,识别一张bitmap,每次执行前都需要重新new一个对象
    mClassifierAsyncTask = new ClassifierAsyncTask();
    mClassifierAsyncTask.execute(bitmap);
}
// 自定义AsyncTask任务类,实现doInBackground
private ClassifierAsyncTask mClassifierAsyncTask;
private class ClassifierAsyncTask extends AsyncTask<Bitmap , Void, String >{
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mTvResult.setText(getString(R.string.classifying));
    }
    @Override
    protected String doInBackground(Bitmap... bitmaps) {
        if(mMyTfClassifier == null) {
            mMyTfClassifier = new MyTfClassifier(MainActivity.this);
        }
        String result = mMyTfClassifier.recognizeImage(bitmaps[0]);
        return result;
    }
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        mTvResult.setText(result);
    }
}
存在的问题
Activity屏幕旋转或销毁时,如果AsyncTask没有执行完毕就会存在内存泄露。特别是屏幕旋转时AsyncTask没有执行完毕,会导致屏幕异常。
Android常用异步任务执行方法的更多相关文章
- Android测试TestSuite的执行方法
		public class StartTest extends InstrumentationTestRunner { public TestSuite getAllTests() { ... 
- 29个android开发常用的类、方法及接口
		在安卓开发中,我们常常都需要借助各种各样的方法.类和接口来实现相关功能.提升开发效率,但对于初学者而言,什么时候该用什么类.方法和接口呢?下面小编整理了29个,日常开发中比较常用的类.方法.接口及其应 ... 
- 使用Task异步执行方法_多线程_应用程序池
		偶然遇到在执行登录的方法需要发送消息队列导致登录时间过长的问题,从网上查了一些方法,先将一个简单的异步处理程序的小例子展示出来,供大家参考: 备注:该方法是从应用程序程序所在的线程池中获取线程,第一次 ... 
- ArcGIS Runtime for Android 使用异步GP服务绘制等值线
		关于基于Android上ArcGIS Server GP服务的调用,已经有前辈给出了很好的例子: http://blog.csdn.net/esrichinacd/article/details/92 ... 
- (转)ArcGIS Runtime for Android 使用异步GP服务绘制等值线
		关于基于Android上ArcGIS Server GP服务的调用,已经有前辈给出了很好的例子: http://blog.csdn.net/esrichinacd/article/details/92 ... 
- Android常用酷炫控件(开源项目)github地址汇总
		转载一个很牛逼的控件收集帖... 第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.Gri ... 
- Android常用库源码解析
		图片加载框架比较 共同优点 都对多级缓存.线程池.缓存算法做了处理 自适应程度高,根据系统性能初始化缓存配置.系统信息变更后动态调整策略.比如根据 CPU 核数确定最大并发数,根据可用内存确定内存缓存 ... 
- Android 常用炫酷控件(开源项目)git地址汇总
		第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.P ... 
- Android 常用开发工具以及Mac常用软件
		Android 常用的开发工具记录.其中包括AndroidStudio(IDEA)插件.Mac 上好用的软件以及国内知名Android开发者博客等. Android Studio 插件 codota ... 
随机推荐
- JAX-WS文章汇总
			学习路线图 传送门 最简单的Web Service实现- 这里提供一个最简单的Web Service的实现,基于JAX-WS.除了jdk不需要任何其他jar包,使用Eclipse提供的Web Serv ... 
- Single Number II(LintCode)
			Single Number II Given 3*n + 1 numbers, every numbers occurs triple times except one, find it. Examp ... 
- 从Linux下载文件到Windows没有换行问题
			这是一个小问题,一般用txt打开文件才会遇到,word打开也是正常(估计其他编程软件打开也正常). 顺便提一下pscp从Linux上下载文件到Windows. C:\Users\xuefei>p ... 
- canvas元素内容生成图片
			转自https://segmentfault.com/a/1190000003853394 想要将canvas元素当前显示的内容生成为图像文件,我们首先要获取canvas中的数据,在HTML5 < ... 
- 【推导】【构造】Petrozavodsk Summer Training Camp 2015 Day 2: Xudyh (TooSimple) Contest, Saturday, August 22, 2015 Problem G. Travelling Salesman Problem
			一个矩阵,每个位置有一个非负整数,一个人从左上走到右下,不能走重复的格子,问得到的最大权值. 当长宽不都为偶数时,必然能走遍所有格子,横着从左到右,从右到左(或是竖着走)走完即可. 当长宽都是偶数时, ... 
- 【FFT】OpenJ_POJ - C17H - Reverse K-th Problem
			对每个位置i处理出以其为结尾,且比a(i)大的数有j个的前缀个数,记成一个数组l:同理,处理出以其为开头,且比a(i)大的数有j个的后缀的个数,记成一个数组r. 整个序列中比a(i)大的数的个数的数组 ... 
- 【区间dp】【记忆化搜索】UVALive - 3516 - Exploring Pyramids
			f(i,j)=sum(f(i+1,k-1)*f(k,j) | i+2<=k<=j,Si=Sk=Sj). f(i+1,k-1)是划分出第一颗子树,f(k,j)是划分出剩下的子树. #incl ... 
- 【最大流Dinic模板】HDU1532&POJ1273-Drainage Ditches(16/3/6更正)
			#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #inc ... 
- bzoj 3728: PA2014Final Zarowki
			3728: PA2014Final Zarowki Description 有n个房间和n盏灯,你需要在每个房间里放入一盏灯.每盏灯都有一定功率,每间房间都需要不少于一定功率的灯泡才可以完全照亮.你可 ... 
- Codeforces Round #343 (Div. 2) A. Far Relative’s Birthday Cake 水题
			A. Far Relative's Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/A Description Do ... 
