HandlerThread 你需要了解的七大姑八大姨


轻松的,随心所欲的解释,才会让代码变得更简单!

1、what is this ?

顾名思义:Handler+Thread实现的一个类,轻量级异步通信,通过Handler实现子线程与主线程的通信

2、How to use ?

Let me show you something ,so easy!

咋们先从开始使用再到源码剖析,准备上车!

五步走战略策略 :

//step 1:创建HandlerThread对象,参数说明:线程名称 or 线程名称+线程优先级
HandlerThread mHandlerThread = new HandlerThread("yourname");

//step 2:启动线程,创建Looper对象,MessageQuene,开启消息循环
mHandlerThread.start();

//step 3:通过HandlerThread的Looper对象创建搬砖线程,复写handleMessage()方法,实现子线程
与主线程的通信,handleMessage()方法其实是执行在HandlerThread 创建的子线程内
static Handler moveBrickHandler = new Handler( mHandlerThread.getLooper() ) {
        @Override
        public boolean handleMessage(Message msg) {
            //消息处理
            return true;
        }
    });
    
//step 4:通过sendMessage()向搬砖线程发送消息,进行消息传递
Message message = Message.obtain();
//消息标识
message .what = FLAG
//消息体
message.obj = OBJECT
//通过搬砖Handler发送消息
moveBrickHandler.sendMessage(message);

//step 5:停止消息,分为两种,后面将会一一解释
mHandlerThread.quit();
//安全退出
mHandlerThread.quitSafely();

这里就不上案例了,很简单,按照上面使用即可!

OK,congratulation! 你已经熟练掌握其使用方法了------ nice, 就这!

3、源码套餐解析一波,请收下它

我们将会根据上面的使用不步骤来一步步讲解源码,建议先了解Handler的使用及原理,才有利于消化哟,Let’s begin !!

step 1:创建HandlerThread对象,参数说明:线程名称 or 线程名称+线程优先级

//继承自Thread类,是一个线程Thread类
public class HandlerThread extends Thread {
	//线程优先级
    int mPriority;
	//当前线程id
    int mTid = -1;
	//当前线程持有的Looper对象
    Looper mLooper;
    //默认优先级
    public HandlerThread(String name) {
        //通过调用父类默认的方法创建线程
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    //自定义设置优先级
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    //-------------------------//
}

step 2:启动线程,创建Looper对象,MessageQuene,开启消息循环

/**
* 源码分析:通过调用start()方法,从而调用到run()方法
*/ 
@Override
public void run() {
	
    //setup 1. 获得当前线程的id
    mTid = Process.myTid();

    //setup 2. 创建Looper对象以及MessageQueue对象,不清楚的建议先阅读Handler源码
    Looper.prepare();

    //setup 3. 通过持有锁机制来获得当前线程的Looper对象
    synchronized (this) {
        mLooper = Looper.myLooper();
       
        //发出通知:当前线程已经成功创建mLooper对象,通知getLooper()方法中的wait()
        notifyAll();
    }

    //setup 4. 设置当前线程的优先级
    Process.setThreadPriority(mPriority);

    //setup 5. 在线程循环前做一些准备工作,该方法实现体是空的,子类可实现 or 不实现该方法
    onLooperPrepared();

    //setup 6. 进行消息循环,不断从MessageQueue中取消息 and 派发消息
    Looper.loop();
	
	//setup 7. 重置线程id
    mTid = -1;
}

//子类选择性实现,主要作为初始化工作
protected void onLooperPrepared() {

}

step 3:通过HandlerThread的Looper对象创建搬砖线程,复写handleMessage()方法,实现子线程与主线程的通信,handleMessage()方法其实是执行在HandlerThread 创建的子线程内,这里主要介绍HandlerThread的getLooper()方法,关于创建Handler可以去了解Handler的创建过程

/**
*getLooper()返回mLooper对象最终是在run()方法中返回,Looper.myLooper()
*/
public Looper getLooper() {
    //判断线程是否存活
    if (!isAlive()) {
        return null;
    } 
    //通过锁机制来实现wait(),notifyAll()
    synchronized (this) {
		//循环判断线程是否存活,以及mLooper对象是否为null
        while (isAlive() && mLooper == null) {
            try {
                //调用wait()方法等待
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

step 4:通过sendMessage()向搬砖线程发送消息,进行消息传递,此处为Handler相关,暂不作具体分析

Message message = Message.obtain();
//消息标识
message .what = FLAG
//消息体
message.obj = OBJECT
//通过搬砖Handler发送消息
moveBrickHandler.sendMessage(message);

step 5:停止消息,分为安全的停止消息和不安全的停止消息,无论是那种方式,最终都会调用MessageQueue的quit(boolean safe)方法

/**
  *MessageQueue.quit(boolean safe)
  */ 
void quit(boolean safe) {
    if (!mQuitAllowed) {
        throw new IllegalStateException("Main thread not allowed to quit.");
    }
    synchronized (this) {
		//是否已经退出,是的话直接返回
        if (mQuitting) {
            return;
        }
        mQuitting = true;
        //是否选择安全退出
        if (safe) {
			//安全退出,首先会判断是否有消息正在处理
            removeAllFutureMessagesLocked();
        } else {
			//不安全的退出,直接遍历列表,移除消息
            removeAllMessagesLocked();
        }
        nativeWake(mPtr);
    }
}
/**
  *遍历Message链表、移除所有消息的回调,重置message为null
  */ 
private void removeAllMessagesLocked() {
    Message p = mMessages;
	//遍历Message链表、移除所有消息的回调
    while (p != null) {
        Message n = p.next;
        p.recycleUnchecked();
        p = n;
    }
    mMessages = null;
}

/**
  *判断当前消息队列是否正在处理消息
  *若不是,则调用removeAllMessagesLocked()移除消息
  *若是,则等待该消息处理处理完毕再调用removeAllMessagesLocked()移除消息
  */ 
private void removeAllFutureMessagesLocked() {

    final long now = SystemClock.uptimeMillis();
    Message p = mMessages;

    if (p != null) {
        // 判断当前消息队列是否正在处理消息
        if (p.when > now) {
			//没有,直接移除所有消息
            removeAllMessagesLocked();
        } else {
			//若是正在处理,则等待该消息处理处理完毕再退出该循环
            Message n;
			//循环获取消息
            for (;;) {
                n = p.next;
                if (n == null) {
                    return;
                }
                if (n.when > now) {
                    break;
                }
                p = n;
            }
            p.next = null;
            do {
                p = n;
                n = p.next;
                p.recycleUnchecked();
            } while (n != null);
        }
    }
}

以上就是大致情况,建议先了解Handler以及Thread,你会更好的理解HandlerThread 哟

最后一步,小结一哈!

  1. 创建HandlerThread 的过程,其实就是创建Thread的过程,通过传入参数线程名称 and
    线程名称和优先级,来创建HandlerThread ,这里的优先级为Android里面的优先
    Process.THREAD_PRIORITY_DEFAULT
  2. 调用HanderThread的start()方法来启动线程,其实是调用Thread的start(),就会回调run()方法,首先是创建MessageQueue以及Looper对象,通过锁机制 wait()与notifyAll()来获取当前线程的mLooper对象,当mLooper对象为空时,getLooper()通过wait()会阻塞,只有当mLooper对象被成功初始化时,通过notifyAll()唤醒,然后通过Looper.loop() 开启循环,不断从messageQueue中取出消息
  3. 通过HandlerThread的getLooper()获取mLooper对象,通过该looper对象创建Handler,实现与HandlerThread创建的线程进行绑定
  4. 消息的停止,分为安全停止与不安全的停止方式,主要区别在于停止消息时,对是否有消息正在进行处理作出不同反应,安全方式需要等待消息执行完之后才会停止,不安全则是直接遍历消息列表,移除消息,重置message

OK,This is ending!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值