Android基础——多线程之HandlerThread

HandlerThread 简介

Handler 必须要和 Looper 中结合使用,尤其在子线程中创建 Handler 的话,需要这样写:

/**
 * @ 子线程写Handler+Looper
 */
private class LooperThread extends Thread {
    private Handler mHandler;

    @Override
    public void run() {
        Looper.prepare();
        super.run();
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        };
        Looper.loop();
    }
}

非常繁琐,还需要手动调用Looper.prepare() 和 Looper.loop(),HandlerThread就是为了省去这些步骤而产生的,下面介绍一下HandlerThread的源码,一共160多行


HandlerThread源码

package android.os;

import android.annotation.NonNull;
import android.annotation.Nullable;

/**
 * Handy class for starting a new thread that has a looper. The looper can then be 
 * used to create handler classes. Note that start() must still be called.
 */
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason isAlive() returns false, this method will return null. If this thread
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    /**
     * @return a shared {@link Handler} associated with this thread
     * @hide
     */
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

    /**
     * Quits the handler thread's looper.
     * <p>
     * Causes the handler thread's looper to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     *
     * @see #quitSafely
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    /**
     * Quits the handler thread's looper safely.
     * <p>
     * Causes the handler thread's looper to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * Pending delayed messages with due times in the future will not be delivered.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p>
     * If the thread has not been started or has finished (that is if
     * {@link #getLooper} returns null), then false is returned.
     * Otherwise the looper is asked to quit and true is returned.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     */
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

从源码中看出HandlerThread有以下特点

1、HandlerThread 是一个Thread,而且是一个包含 Looper 的 Thread,我们可以直接使用这个 Looper 创建 Handler;

2、HandlerThread创建完成必须调用start( )方法,就会去执行run( )方法;

3、也可以指定线程的优先级,注意使用的是 android.os.Process 而不是 java.lang.Thread 的优先级;

4、quit和quitSafely都是退出HandlerThread的消息循环。其分别调用Looper的quit和quitSafely方法。 
quit方法会将消息队列中的所有消息移除(延迟消息和非延迟消息)。 
quitSafely会将消息队列所有的延迟消息移除,非延迟消息派发出去让Handler去处理。quitSafely相比于quit方法安全之处在于清空消息之前会派发所有的非延迟消息;

5、HandlerThread适合处理本地IO读写操作(数据库,文件),因为本地IO操作大多数的耗时属于毫秒级别,对于单线程 + 异步队列的形式 不会产生较大的阻塞。而网络操作相对比较耗时,容易阻塞后面的请求,因此在这个HandlerThread中不适合加入网络操作

 


举个例子

先上效果图,每次点击button,产生一个随机数显示在textview上

常规使用步骤

1、创建HandlerThread对象handlerThread

handlerThread = new HandlerThread("handlerthread");

2、启动handlerThread

handlerThread.start();

3、创建异步subHandler,绑定Looper(也可以使用Handler.Callback形式)

subHandler = new SubHandler(handlerThread.getLooper());

4、创建消息循环处理机制,异步subHandler发送数据到主线程Handler更新UI

@Override
public void handleMessage(Message msg) {
	super.handleMessage(msg);
	try{
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	Message msg1 = new Message();
	msg1.what = MSG_RESULT;
	msg1.obj = Math.random();
	mUiHandler.sendMessage(msg1);
}

这样整个Handler+Looper+MessageQueen+message循环消息处理机制就搭建完成

贴下整个Java代码,布局文件很简单就不贴了

package com.example.handlerthreaddemo;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

/**
 * @ Introduce the method of using HandlerThread
 * @ 8.7 2018
 */
public class HandlerThreadActivity extends AppCompatActivity {

    private Button button;
    private TextView textView;

    private HandlerThread handlerThread;
    private SubHandler subHandler;
    private static int MSG_GET = 0;
    private static int MSG_RESULT = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread);
        textView = findViewById(R.id.textView);
        button = findViewById(R.id.button);

        handlerThread = new HandlerThread("handlerthread");
        handlerThread.start();

        subHandler = new SubHandler(handlerThread.getLooper());
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                subHandler.sendEmptyMessage(MSG_GET);
            }
        });
    }

    private class SubHandler extends Handler {
        public SubHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            try{
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Message msg1 = new Message();
            msg1.what = MSG_RESULT;
            msg1.obj = Math.random();
            mUiHandler.sendMessage(msg1);
        }
    }

    private Handler mUiHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    String str = msg.obj.toString();
                    if(str != null){
                        textView.setText("num = "+str);
                    }
                    break;
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handlerThread.quitSafely();
    }

}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值