前面已经提到过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. BZOJ_1036_[ZJOI2008]_树的统计Conut_(树链剖分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1036 给出一棵树以及各点的权值,对数进行如下三种操作: 1.改变某一节点u的值为t; 2.求节 ...

  2. asp.net 前后台交互

    转自:http://www.cnblogs.com/softpower/archive/2010/11/16/1878769.html 1.如何在JavaScript访问C#函数? 2.如何在Java ...

  3. devpress 很好的中文论坛

    阿伟邀请您访问DXPER开发者论坛http://www.dxper.net/?fromuid=3701

  4. sql server 自定义函数

    create function 函数名 (@pno int) returns int as begin declare @a int if not exists(select * from perso ...

  5. Oracle错误

    System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本 这个是我页面报的错误,请帮解答 在错误出现的时候我第一时间现在了一个oracle客户端软件,然 ...

  6. Get the largest sum of contiguous subarray in an int array

    When I finished reading this problem,I thought I could solve it by scanning every single subarray in ...

  7. Dynamic Library Design Guidelines

    https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100 ...

  8. 30种mysql优化sql语句查询的方法

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索 ...

  9. hdoj 2795 Billboard【线段树区间最大值】

    Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  10. 一个空格引发的bug

    好久没写博客了. 我们的一个项目用的thinkphp框架,当在debug模式下面运行很正常,但切换到生产模式时,刷新页面第一次可以正常显示,刷新第二次会出现错误如下: Fatal error: Cal ...