Handler 原理分析和使用之HandlerThread

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

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

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

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

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

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

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

 1 import android.os.AsyncTask;
 2 import android.support.v7.app.AppCompatActivity;
 3 import android.os.Bundle;
 4 import android.view.View;
 5 import android.widget.Button;
 6 import android.widget.TextView;
 7
 8
 9 public class MainActivity extends AppCompatActivity implements View.OnClickListener{
10
11     private TextView myTextView;
12     private Button myButton;
13     private MyAsyncTask myTask;
14     @Override
15     protected void onCreate(Bundle savedInstanceState) {
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.activity_main);
18         myTextView = (TextView)this.findViewById(R.id.text_view);
19         myButton = (Button)this.findViewById(R.id.post);
20         myButton.setOnClickListener(this);
21         //主线程初始化异步任务
22         myTask = new MyAsyncTask();
23         //主线程启动异步任务,
24         myTask.execute(10);
25     }
26
27     @Override
28     public void onClick(View v) {
29         //主线程取消异步任务
30         myTask.cancel(true);
31     }
32
33     /**
34      * AsyncTask<T, Q, K> 是异步任务基类  包含三个泛型参数。
35      * T 类型参数为执行异步任务时的参数类型doInBackground(T)
36      * Q 类型参数为执行过程中的参数类型onProgressUpdate(Q)
37      * K 类型参数为执行结束onPostExecute(K)或中取消执行时的类型参数onCancelled(K)
38      */
39     class MyAsyncTask  extends AsyncTask<Integer, Integer, Long>{
40
41         @Override
42         //执行异步任务核心方法,主语T参数类型
43         protected Long doInBackground(Integer... params) {
44             int size = params[0];
45             long totalSize = 0l;
46             for(int i = 0; i < size; i++){
47                 totalSize += 10000;
48                 publishProgress((int) ((i / (float) size) * 100));
49                 if(isCancelled()){
50                     break;
51                 }
52                 try {
53                     Thread.sleep(1000);
54                 } catch (InterruptedException e) {
55                     e.printStackTrace();
56                 }
57             }
58             return totalSize;
59         }
60
61         @Override
62         //开始执行异步任务前,更新UI线程。
63         protected void onPreExecute() {
64             myTextView.setText("downLoad start !!");
65         }
66
67         @Override
68         //执行异步任务中,更新UI线程
69         protected void onProgressUpdate(Integer... values) {
70             int progress = values[0];
71             myTextView.setText(progress + "%");
72         }
73
74         @Override
75         //执行异步任务后,更新UI线程
76         protected void onPostExecute(Long aLong) {
77             myTextView.setText("Task finished");
78         }
79
80         @Override
81         //执行异步任务被取消后,跟新UI线程
82         protected void onCancelled(Long aLong) {
83             myTextView.setText("Task camcelled");
84         }
85     }
86 }

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

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

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

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

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

 1 import android.os.Handler;
 2 import android.os.Looper;
 3 import android.os.Message;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.util.Log;
 7 import android.view.View;
 8 import android.widget.Button;
 9 import android.widget.TextView;
10 import java.util.concurrent.ArrayBlockingQueue;
11 import java.util.concurrent.BlockingQueue;
12
13
14 public class MainActivity extends AppCompatActivity implements View.OnClickListener{
15
16     private TextView myTextView;
17     private Button myButton;
18     private MyThread myThread;
19     private Handler myThreadHandler;
20     private int count = 0;
21     @Override
22     protected void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.activity_main);
25         myTextView = (TextView)this.findViewById(R.id.text_view);
26         myButton = (Button)this.findViewById(R.id.post);
27         myButton.setOnClickListener(this);
28         //定义子线程
29         myThread = new MyThread();
30         //获取子线程的Handler
31         myThreadHandler = myThread.getHandler();
32         //启动子线程
33         myThread.start();
34
35     }
36
37     @Override
38     public void onClick(View v) {
39         count++;
40         //通过子线程的Handler,主线程给子线程发送消息(添加任务)
41         myThreadHandler.sendEmptyMessage(count);
42     }
43
44     /**
45      * 子线程
46      */
47     public class MyThread extends Thread{
48         public Handler mThreadHandler = null;
49         //任务队列
50         public BlockingQueue<Integer> queue  = null;
51         public MyThread(){
52             super();
53             queue  = new ArrayBlockingQueue<Integer>(20);
54             //获取子线程的Looper
55             Looper mThreadLopper = Looper.myLooper();
56             //初始化子线程的Handler
57             mThreadHandler = new Handler(mThreadLopper, new Handler.Callback() {
58                 @Override
59                 //接收到主线程发的任务
60                 public boolean handleMessage(Message msg) {
61                     //任务添加到队列
62                     queue.add(msg.what);
63                     return false;
64                 }
65             });
66         }
67         public Handler getHandler(){
68             return mThreadHandler;
69         }
70         public void run(){
71             while(true){
72                 try{
73                     //任务的处理
74                     int what = queue.take();
75                     Log.e("Test", "Click Button = " + what);
76                 }catch(InterruptedException e){
77
78                 }
79
80             }
81         }
82
83     }
84 }

上面的例子说明了两件事情。第一,非主线程有自己的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完了。

时间: 2024-08-05 17:14:55

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

Handler 原理分析和使用(一)

我为什么写Handler,原因主要还在于它在整个 Android 应用层面非常之关键,他是线程间相互通信的主要手段.最为常用的是其他线程通过Handler向主线程发送消息,更新主线程UI. 下面是一个最简单的例子. 1 import android.os.Handler; 2 import android.os.Message; 3 import android.support.v7.app.AppCompatActivity; 4 import android.os.Bundle; 5 imp

handler机制原理分析(适合初学者)1.0

任何一个APK都是从framework层的ActivityThread的main()函数中开始执行,接着调用prepareMainLooer()为UI线程创建一个消息队列MessageQueue.并执行Looper.loop(). Handler消息机制的原理是什么了?我们先来写一个程序看看. 首先看new Handler().做了什么 可以看出在new Handler()中获取了Loop,messagequeue,callback,等对象. 接下来看handler.sendEmptyMessa

Handler系列之原理分析

上一节我们讲解了Handler的基本使用方法,也是平时大家用到的最多的使用方式.那么本节让我们来学习一下Handler的工作原理吧!!! 我们知道Android中我们只能在ui线程(主线程)更新ui信息,那么你们知道为什么只能通过Handler机制更新ui吗?其实最根本的目的就是解决多线程并发的问题. 假设在一个Activity中有多个线程去更新ui,并且都没有加锁,那么会是什么样子? 导致的结果就是更新界面错乱. 如果对更新ui的操作都进行加锁处理的话又产生什么问题哪? 性能下降. 处于对以上

Android中Thread、Handler、Looper、MessageQueue的原理分析

在Android开发当中,Thread.Handler.Looper这几个类是特别常见,在刚开始学习Android的时候对这些类可能并不是很清晰.下面我们就一起从源码的角度剖析一下这几个类的工作原理. Thread 首先是Thread, 我们都知道一个Thread就是一个线程对象,只要在run方法中填写自己的代码然后启动该线程就可以实现多线程操作.例如 : new Thread(){ public void run() { // 耗时的操作 }; }.start(); 我们知道,针对上面的代码中

Android视图SurfaceView的实现原理分析

附:Android控件TextView的实现原理分析 来源:http://blog.csdn.net/luoshengyang/article/details/8661317 在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面.由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制.又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输

Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解

概况 Android在4.3的版本中(即API 18)加入了NotificationListenerService,根据SDK的描述(AndroidDeveloper)可以知道,当系统收到新的通知或者通知被删除时,会触发NotificationListenerService的回调方法.同时在Android 4.4 中新增了Notification.extras 字段,也就是说可以使用NotificationListenerService获取系统通知具体信息,这在以前是需要用反射来实现的. 转载请

alljoyn:基于java动态代理的RPC实现原理分析

alljoyn是由高通开源,allseen组织下,作为IOT的一个开源软件框架. 本文分析它的core部分的远程调用方法的实现过程. 以android core sdk的release版本中的simple程序为例子. (eg alljoyn-14.06.00a-android-sdk-rel\alljoyn-android\core\alljoyn-14.06.00a-rel\java\samples\simple\client) 1. 下面是一个定义为alljoyn接口,并定义了一个远程调用方

Redis数据持久化机制AOF原理分析二

Redis数据持久化机制AOF原理分析二 分类: Redis 2014-01-12 15:36  737人阅读  评论(0)  收藏  举报 redis AOF rewrite 目录(?)[+] 本文所引用的源码全部来自Redis2.8.2版本. Redis AOF数据持久化机制的实现相关代码是redis.c, redis.h, aof.c, bio.c, rio.c, config.c 在阅读本文之前请先阅读Redis数据持久化机制AOF原理分析之配置详解文章,了解AOF相关参数的解析,文章链

RemoteViews原理分析及应用

转载请注明出处:http://blog.csdn.net/ahence/article/details/62418926 RemoteViews基本概念 RemoteViews乍一看名字似乎也是一种View,实则不然,它并不是View.来看RemoteViews的定义及官方说明: /** * A class that describes a view hierarchy that can be displayed in * another process. The hierarchy is in