前面已经提到过Handler的原理以及Handler的三种用法。这里做一个非常简单的一个总结:

  • Handler 是跨线程的Message处理。负责把Message推送到MessageQueue和处理。
  • Looper 用来轮询MessageQueue,获取Message 发送给指定的Handler进行处理。
  • Looper 需要和线程绑定,绑定那个线程,Handler就会在那个线程处理Message

前两篇文章使用Handler处理的场景是:主线程(UI线程)被子线程更新。即使用主线程的Handler和Looper,在子线程中发Message。然后主线程处理 handlerMessage。

-----------------------------------------------------------------------------------------

下面反过来说,如何从UI线程发消息,让子线程处理。

最为通常的做法是:new Thread().start。起一个线程去完成一个任务,任务完成线程就可以自毙了。当然了如果不需要子线程返回结果,而且只有一个线程,那么这是最简单的了。

另一种方法是SyncTask。实例如下:

 import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView myTextView;
private Button myButton;
private MyAsyncTask myTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView = (TextView)this.findViewById(R.id.text_view);
myButton = (Button)this.findViewById(R.id.post);
myButton.setOnClickListener(this);
//主线程初始化异步任务
myTask = new MyAsyncTask();
//主线程启动异步任务,
myTask.execute(10);
} @Override
public void onClick(View v) {
//主线程取消异步任务
myTask.cancel(true);
} /**
* AsyncTask<T, Q, K> 是异步任务基类 包含三个泛型参数。
* T 类型参数为执行异步任务时的参数类型doInBackground(T)
* Q 类型参数为执行过程中的参数类型onProgressUpdate(Q)
* K 类型参数为执行结束onPostExecute(K)或中取消执行时的类型参数onCancelled(K)
*/
class MyAsyncTask extends AsyncTask<Integer, Integer, Long>{ @Override
//执行异步任务核心方法,主语T参数类型
protected Long doInBackground(Integer... params) {
int size = params[0];
long totalSize = 0l;
for(int i = 0; i < size; i++){
totalSize += 10000;
publishProgress((int) ((i / (float) size) * 100));
if(isCancelled()){
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return totalSize;
} @Override
//开始执行异步任务前,更新UI线程。
protected void onPreExecute() {
myTextView.setText("downLoad start !!");
} @Override
//执行异步任务中,更新UI线程
protected void onProgressUpdate(Integer... values) {
int progress = values[0];
myTextView.setText(progress + "%");
} @Override
//执行异步任务后,更新UI线程
protected void onPostExecute(Long aLong) {
myTextView.setText("Task finished");
} @Override
//执行异步任务被取消后,跟新UI线程
protected void onCancelled(Long aLong) {
myTextView.setText("Task camcelled");
}
}
}

通过实例可以看出,SyncTask不但可以给主线程提供启动和停止接口,还可以给主线程上报过程。当然了开销也是有的。

实际上这种方式也可以用 Handler 原理分析和使用(一)中的例子实现。

以上都是主线程启动一个子线程完成任务。但是如果要做多个异步任务,该如何实现?

首先,从多个异步任务来考虑,如果还是各自不同的话,先考虑到的是线程池。这个在后面的多线程部分在说明。

还有一种方式就是使用HandlerThread。这个就是通过主线程获取其他线程给HandlerThread发消息,使其完成相关的任务。在例举说明HandlerThread使用之前,先看看以下例子。也是主线程给子线程发消息,让子线程处理任务。

 import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView myTextView;
private Button myButton;
private MyThread myThread;
private Handler myThreadHandler;
private int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView = (TextView)this.findViewById(R.id.text_view);
myButton = (Button)this.findViewById(R.id.post);
myButton.setOnClickListener(this);
//定义子线程
myThread = new MyThread();
//获取子线程的Handler
myThreadHandler = myThread.getHandler();
//启动子线程
myThread.start(); } @Override
public void onClick(View v) {
count++;
//通过子线程的Handler,主线程给子线程发送消息(添加任务)
myThreadHandler.sendEmptyMessage(count);
} /**
* 子线程
*/
public class MyThread extends Thread{
public Handler mThreadHandler = null;
//任务队列
public BlockingQueue<Integer> queue = null;
public MyThread(){
super();
queue = new ArrayBlockingQueue<Integer>(20);
//获取子线程的Looper
Looper mThreadLopper = Looper.myLooper();
//初始化子线程的Handler
mThreadHandler = new Handler(mThreadLopper, new Handler.Callback() {
@Override
//接收到主线程发的任务
public boolean handleMessage(Message msg) {
//任务添加到队列
queue.add(msg.what);
return false;
}
});
}
public Handler getHandler(){
return mThreadHandler;
}
public void run(){
while(true){
try{
//任务的处理
int what = queue.take();
Log.e("Test", "Click Button = " + what);
}catch(InterruptedException e){ } }
} }
}

上面的例子说明了两件事情。第一,非主线程有自己的Looper(很多文章说没有),第二Handler可以处理非主线程的任务。实际上上面的例子,使用了sendMessage()方法,其实际上用处并不是很广泛,甚至有些憋屈,本身已经有了一个MessageQueue,为什么还要使用一个ArrayBlockingQueue?

实际上上述的例子,完全可以通过HandlerThread来替代。例子如下

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ public TextView myTextView;
private Button myButton;
private HandlerThread myThread;
private Handler myThreadHandler;
private int count = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView = (TextView)this.findViewById(R.id.text_view);
myButton = (Button)this.findViewById(R.id.post);
myButton.setOnClickListener(this);
//初始化HandlerThread
myThread = new HandlerThread("handlerThread_test");
//启动HandlerThread
myThread.start();
//初始化HandlerThrand的Handler对象
myThreadHandler = new Handler(myThread.getLooper(), new Handler.Callback() {
@Override
//实现消息处理。
public boolean handleMessage(Message msg) {
int what =msg.what;
Log.e("Test", "Click Button = " + what);
return false;
}
});
} @Override
public void onClick(View v) {
count++;
//通过Handler给HandlerThread线程发送消息
myThreadHandler.sendEmptyMessage(count);
//通过Handler给HandlerThreand发送要执行的任务。
myThreadHandler.post(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("Test", "Hello world1");
}
});
myThreadHandler.post(new Runnable() {
@Override
public void run() {
Log.e("Test", "Hello world2");
}
});
}
}

从这个例子不难看出HandlerThread实际上是一个Thread,而这个Thread是负责处理Handler派发的消息和任务。此外值得注意有三点:

第一,只有一个线程来处理各种任务。

第一,执行的任务时有序的。也就是说顺序可以被控制。

第二,可以执行各种自定义的任务。

最后关于HandlerThread的退出:myThread.quit();

HandlerThread与SyncTask相比较,缺少执行过程的反馈。但是执行任务的多样性超过SyncTask。当然了都只启动了一个线程。

HandlerThread与Handler-Thread模式比较,也是缺少执行反馈。但是执行多任务时,HandlerThread却只需要一个线程。

所有的Handler就到这里了。也不经意间把SyncTask拿出来溜了一下。其他两篇

Handler 原理分析和使用(一)

Handler 原理分析和使用(二)

Handler完了。

Handler 原理分析和使用之HandlerThread的更多相关文章

  1. Handler 原理分析和使用(二)

    在上篇 Handler 原理分析和使用(一)中,介绍了一个使用Handler的一个简单而又常见的例子,这里还有一个例子,当然和上一篇的例子截然不同,也是比较常见的,实例如下. import andro ...

  2. Handler 原理分析和使用(一)

    我为什么写Handler,原因主要还在于它在整个 Android 应用层面非常之关键,他是线程间相互通信的主要手段.最为常用的是其他线程通过Handler向主线程发送消息,更新主线程UI. 下面是一个 ...

  3. Handler系列之原理分析

    上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信 ...

  4. [转]Handler MessageQueue Looper消息循环原理分析

    Handler MessageQueue Looper消息循环原理分析   Handler概述 Handler在Android开发中非常重要,最常见的使用场景就是在子线程需要更新UI,用Handler ...

  5. Android中Input型输入设备驱动原理分析(一)

    转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反 ...

  6. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

  7. 转载:solr MoreLikeThis的原理分析

    转载地址:http://blog.sina.com.cn/s/blog_5ddc071f0101muos.html 在solr中有两种方式实现MoreLikeThis:MoreLikeThisHand ...

  8. WebViewJavascriptBridge 原理分析

    WebViewJavascriptBridge 原理分析 网上好多都是在介绍 WebViewJavascriptBridge如何使用,这篇文章就来说说 WebViewJavascriptBridge ...

  9. Android中Input型输入设备驱动原理分析<一>

    话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反正这个是没变的,在android的底层开发中对于Linux的基本驱动程序设计还是没变的,当然Android底层机制也 ...

随机推荐

  1. POJ_3579_Median_(二分,查找第k大的值)

    描述 http://poj.org/problem?id=3579 给你一串数,共C(n,2)个差值(绝对值),求差值从大到小排序的中值,偶数向下取. Median Time Limit: 1000M ...

  2. NOI2003 文本编辑器editor

    1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1908  Solved: 738[Submit][Statu ...

  3. WinDump使用方法

    转自:http://blog.csdn.net/weiyuweizhi/article/details/4326174 在命令行下启动windump.exe 参数列表: -a              ...

  4. RatingBar设置显示星星个数

    RatingBar评分控件 项目中遇到问题 marker一下: 关于自定义以及遇到的出现模糊情况 多半是因为切得图除颜色外 不一致的原因 如果大小也不一样,(沃日) 问题是这样的: 我可以通过OnRa ...

  5. 64位windows7 上安装32位oracle 10g 的方法

    操作系统: windows7 中文旗舰版 oracle安装版本: 10.2.0.1 中文版,升级补丁至 10.2.0.3 下面说正题首先,我们要解除oracle安装的windows版本检测1.编辑安装 ...

  6. java基础(十八)IO流(一)

    这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...

  7. Android学习笔记(十二)BroadcastReceiver的有序广播和优先级

    前两篇博文中简单整理了普通广播,其实还有有序广播,有序广播在开发中也是比不可少的,可以给广播接收者设定优先级来控制接受顺序,并却可以中断广播传递等等. 一.两种Broadcast: · 普通广播(No ...

  8. nginx一致性hash及应用场景。

    考虑一种场景. 多台web服务. 1 后台添加用户,更新用户信息,要求管理员能够实时看到变化. 2 前台用户允许1分钟后生效. nginx 配置一致性hash1. https://github.com ...

  9. HDU 4714 Tree2cycle DP 2013杭电热身赛 1009

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714 Tree2cycle Time Limit: 15000/8000 MS (Java/Other ...

  10. phpDesigner 7.2.5 注册码 更改 语法高亮 主题

    注册码: 用户名:www.xiazaiba.com 序列号:43AB0D432A29EE238CCE0F884D84D8A18498498E98298A98568AD05A0B40 验证码:7S2FF ...