前面已经提到过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. CentOS6.5 x86_64 配置Broadcom 43XX系列 无线网卡驱动

    from: http://wiki.centos.org/HowTos/Laptops/Wireless/Broadcom?action=show In order to install Broadc ...

  2. JS思维导图

  3. Spring之HelloWorld再起

    第一步:打开File->New->Other…,选择Java Project,创建标准Java项目. 第二步:在项目下添加lib文件夹用于存放jar文件,resources用于存放xml配 ...

  4. 【单页应用】view与model相关梳理(转载)

    [单页应用]view与model相关梳理 前情回顾 根据之前的学习,我们形成了一个view与一个messageCenterview这块来说又内建了一套mvc的东西,我们这里来理一下首先View一层由三 ...

  5. SQL SERVER 自定义函数 整数转成指定长度的16进制 转换成指定长度的16进制 不足补0

    最近做项目扩展的时候,遇到问题就是将整型转换成指定长度的16进制 刚开始就是直接使用 cast(12 as varbinary(4))但是发现这个不能解决我的问题 所以就上网搜了一下,然后改了改,下面 ...

  6. 2013 ACM区域赛长沙 C Collision HDU 4793

    题意:在平面上0,0点,有一个半径为R的圆形区域,并且在0,0点固定着一个半径为RM(<R)的圆形障碍物,现在圆形区域外x,y,有一个半径 为r的,并且速度为vx,vy的硬币,如果硬币碰到了障碍 ...

  7. Web 应用性能和压力测试工具 Gor - 运维生存时间

    Web 应用性能和压力测试工具 Gor - 运维生存时间 undefined 无需花生壳,dnspod实现ddns - 推酷 undefined

  8. Shell while循环

    while循环用于不断执行一系列命令,也用于从输入文件中读取数据:命令通常为测试条件.其格式为: while command do Statement(s) to be executed if com ...

  9. Junit 断言 assertThat Hamcrest匹配器

    junit断言总结本文参考了http://blog.csdn.net/wangpeng047/article/details/9628449一 junit断言1.JUnit框架用一组assert方法封 ...

  10. Apache Commons 工具类

    http://blog.csdn.net/feicongcong/article/details/53374399http://blog.csdn.net/hsienhua/article/detai ...