AsyncTask

  AsyncTask 是一种轻量级的异步任务类,可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程用于更新UI。

可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

  AsyncTask 并不合适进行特别耗时的后台任务,对于特别耗时的任务来说,建议使用线程池。

AsyncTask 和 Handler对比:

1 )  Async使用的优点:

  l  简单,快捷

  II 过程可控

使用的缺点:

  l  在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

2 )Handler异步实现的原理和适用的优缺点

  在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)

运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。

  使用的优点:

  l  结构清晰,功能定义明确

  lI  对于多个后台任务时,简单,清晰

使用的缺点:

  l  在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

Android 的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。

AsyncTask定义了三种泛型类型 Params,Progress和Result。

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。
  • Progress 后台任务执行的百分比。
  • Result 后台执行任务最终返回的结果,比如String。

使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

  • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
  • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

有必要的话你还得重写以下这三个方法,但不是必须的:

  • onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
  • onPreExecute()        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
  • onCancelled()             用户调用取消时,要做的操作

使用AsyncTask类,以下是几条必须遵守的准则:

  • Task的实例必须在UI thread中创建;
  • execute方法必须在UI thread中调用;
  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
  • 该task只能被执行一次,否则多次调用时将会出现异常;

HandlerThread

  HandlerThread 其实是一种Thread,它是可以使用Handler的THread,它的实现其实很简单就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop来开启消息循环,这样在实际的使用

中就允许在HandlerThread中创建Handler了。

private void init4(){
//创建一个线程,线程名字:handler-thread
myHandlerThread = new HandlerThread( "handler-thread") ;
//开启一个线程
myHandlerThread.start();
//在这个线程中创建一个handler对象
Log.d(TAG, "init4: "+Thread.currentThread().getId());
handler3 = new Handler( myHandlerThread.getLooper() ){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
Log.d(TAG , "消息: " + msg.what + " 线程: " + Thread.currentThread().getId() ) ;
}
}; //在主线程给handler发送消息
handler3.sendEmptyMessage( 1 ) ; new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "new runnable "+Thread.currentThread().getId());
//在子线程给handler发送数据
handler3.sendEmptyMessage( 2 ) ;
}
}).start() ;
}

  •  在上述代码中,通过HandlerThread开启一个新的线程,将主线程中的Loop转到子线程中处理,降低了主线程的压力,

使主界面更流畅。  它有自己的MessageQueue不会干涉主线程中的消息队列。

  • 程序中如果将此HandlerThread注释掉,程序会出错,因为它会在主线程中发消息给主线程去处理。
  •  在HandlerThread内部消息,处理任务是串行执行,消息是顺序到达的。当队列中某个任务执行时间较长时,后续的任务就会被延迟处理。

利用HandlerThread将Runnable运行在子线程的工具类

public class BackTaskRunner {
private static final String TAG = "BackTaskRunner";
private HandlerThread handlerThread;
private Handler handler; private BackTaskRunner() {
handlerThread = new HandlerThread(TAG);
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
} public static Handler getHandler() {
return SingletonHolder.sRunner.handler;
} private static class SingletonHolder {
static BackTaskRunner sRunner = new BackTaskRunner();
}
}

将代码运行在子线程:

BackTaskRunner.getHandler().post(new Runnable() {
@Override
public void run() {
//需要运行的代码
}
});

AsyncTask、HandlerThread、IntentService和线程池的更多相关文章

  1. Android 应用开发 之通过AsyncTask与ThreadPool(线程池)两种方式异步加载大量数据的分析与对比--转载

     在加载大量数据的时候,经常会用到异步加载,所谓异步加载,就是把耗时的工作放到子线程里执行,当数据加载完毕的时候再到主线程进行UI刷新.在数据量非常大的情况下,我们通常会使用两种技术来进行异步加载,一 ...

  2. Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池

    前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...

  3. AsyncTask两种线程池

        AsyncTask两种线程池  http://bbs.51cto.com/thread-1114378-1.html (API 3.0以后): 1.THREAD_POOL_EXECUTOR, ...

  4. Android AsyncTask内部线程池异步执行任务机制简要分析

    如下分析针对的API 25的AsyncTask的源码: 使用AsyncTask如果是调用execute方法则是同步执行任务,想要异步执行任务可以直接调用executeOnExecutor方法,多数情况 ...

  5. 《Android开发艺术探索》读书笔记 (11) 第11章 Android的线程和线程池

    第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...

  6. Android的线程和线程池

    ---恢复内容开始--- 一.Android线程的形态 (一)AsyncTask解析 AysncTask简介:①.实现上封装了Thread和Handler   ②.不适合进行特别耗时的后台任务 Ays ...

  7. 《android开发艺术探索》读书笔记(十一)--Android的线程和线程池

    接上篇<android开发艺术探索>读书笔记(十)--Android的消息机制 No1: 在Android中可以扮演线程角色的有很多,比如AsyncTask.IntentService.H ...

  8. 《Android开发艺术探索》第11章 Android的线程和线程池

    第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...

  9. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

随机推荐

  1. (二分匹配 模板 KM)奔小康赚大钱--hdu--2255

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=2255 代码: #include <iostream> #include <cstdio ...

  2. 安装Tomcat时 ,设置JAVA_HOME和JRE_HOME

    http://blog.csdn.net/xw370457549/article/details/21638827 安装tomcat后,运行startup.bat提示JAVA_HOME.JRE_HOM ...

  3. [翻译] FastReport 格式化和突出显示

    一:格式化一个值 聚合函数的一个特征是,返回的数值没有格式化,如如下例子所示,它使用"SUM": 数据字段通常返回一个格式化的值,这是一个没有任何变化的"文本" ...

  4. delphi字符串固定长度换行

    var   str,capstr:string;   i,j:integer;   .................... j:=500;   //这个地方可能要根据你显示的宽度来换算对应的字符长度 ...

  5. Keil5编译STM32注意事项

    硬件:某STM32开发板,ST-Link/V2 一.硬件相关: 1.引脚连接: pin7 <-> SWIO pin9 <-> SWCLK pin20/pin18 <-&g ...

  6. 译:微软发布.NET应用架构指南草案

    原文<Microsoft Announces Draft .NET Architecture Guidance> 译注:上周微软发布了全新的<.NET应用架构指南>草案,以征求 ...

  7. HttpClient4.X发送Get请求的url参数拼接

    HttpClient4.X发送Get请求的参数拼接 使用httpClient发送get请求时,请求参数可以以?key=val&key1=val1的拼接到url后面. 但是请求参数较多时,这种方 ...

  8. asp.net—执行分页存储过程的函数

    分页存储过程的T—SQL在之前的文章中已经跟大家分享过了 现在就对应 分页存储过程 跟大家分享下在.net中执行的函数. 该文章是希望给予新手一些编程过程中的帮助(大神可以帮忙指出代码中的不妥之处) ...

  9. springboot-登录拦截器

    小伙伴们大家好,今天给大家分享一个简单的springboot版登录拦截器 首先我们需要在springboot的启动类中让它实现WebMvcConfigurer 这个接口 比如: public clas ...

  10. AGC002F Leftmost Ball

    题目传送门 Description \(n\)种颜色的球,每种\(k\)个,\((n,k\leq 2000)\)将\(n\cdot k\)个球排成一排,把每种颜色最左边的那个涂成白色(初始不含白色), ...