Android面试系列文章2018之Android部分HandlerThread机制篇

1.HandlerThread是什么?

  产生的背景:开启子线程进行耗时操作,多次创建和销毁子线程是很耗费资源的,但是木有关系,谷歌考虑了这点为我们专门开发出了HandlerThread机制,那么它有什么特点呢?请看下面。

  本质:Handler + Thread + Looper,是一个Thread内部有Looper。当你被面试官问道HandlerThread是什么,有何特点,那么你应该这么回答:

  a.HandlerThread本质上是一个线程类,它继承了Thread。

  b.HandlerThread有自己内部的Looper对象,可以进行Looper循环。

  c.通过获取HandlerThread的Looper对象传递给Handler对象,可以在handlerMessage方法中执行异步任务。

  d.优点是不会有堵塞,减少对性能的消耗,缺点是不能进行多任务的处理,需要等待进行处理,处理效率较低。

  e.与线程池注重并发不同,HandlerThread是一个串行队列,HandlerThread背后只有一个线程。

2.HandlerThread的使用

  其实HandlerThread的使用就是为了主线程通知子线程,再由子线程通知主线程,这里面建立一套完整的通信体系,并不像传统的开启子线程,使用HandlerThread的好处就是主线程可以发送信息告诉子线程要干什么,而且可以一直发送信息,无论在主线程的何处,都可以发送合适的信息告诉子线程,它要干什么,子线程做完了信息中交代的事情,然后再通知主线程更新等操作。说白了HandlerThread提供了主线程向子线程的通信。

public class MainActivity extends AppCompatActivity {    private ImageView imageView;    private HandlerThread handlerThread;    /**     * 图片地址数组     */    private String url[]={        "图片地址1","图片地址2","图片地址3","图片地址4","图片地址5"    };    private Handler uiHandler = new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            //加载图片            imageView.setImageBitmap((Bitmap) msg.obj);        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = findViewById(R.id.iv1);        handlerThread = new HandlerThread("downloadImage");        //必须开启HandlerThread线程        handlerThread.start();        //获取子Handler        Handler childHandler = new Handler(handlerThread.getLooper(),new ChildCallback());        for(int i=0;i

  在上面代码中,创建了两个Handler,一个用于更新UI线程的uiHandler,一个是用于异步下载图片的childHandler。最终的结果是childHandler会每个隔1秒钟通过sendEmptyMessageDelayed方法去通知ChildCallback的回调函数handleMessage方法去下载图片并告诉mUIHandler去更新UI界面,以上便是HandlerThread常规使用。

3.HandlerTread机制原理

下面我们通过源码来分析一下HandlerThread:

public class HandlerThread extends Thread {    int mPriority;    int mTid = -1;    Looper mLooper;    public HandlerThread(String name) {        super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;    }    protected void onLooperPrepared() {    }    @Override    public void run() {        mTid = Process.myTid();        Looper.prepare();        synchronized (this) {            mLooper = Looper.myLooper();            notifyAll();    //唤醒其他线程的等待锁,这边是为了唤醒getLooper()方法中的等待锁        }        Process.setThreadPriority(mPriority);        onLooperPrepared();        Looper.loop();        mTid = -1;    }            public Looper getLooper() {        if (!isAlive()) {            return null;        }        // 线程开始,该方法会一直等待Looper对象创建完成才会执行,                       synchronized (this) {            while (isAlive() && mLooper == null) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mLooper;    }        public boolean quit() {        Looper looper = getLooper();        if (looper != null) {            looper.quit();            return true;        }        return false;    }        public boolean quitSafely() {        Looper looper = getLooper();        if (looper != null) {            looper.quitSafely();            return true;        }        return false;    }        public int getThreadId() {        return mTid;    }}

  首先我们看一下它的run()方法,可以发现该方法中调用Looper.myLooper()创建了一个Looper对象mLooper,并把该对象放到线程变量sThreadLocal中,然后通过调用Looper.loop()开启消息循环,Looper.loop()方法会不断循环从MessageQueue中取出消息处理消息,没有消息是则会阻塞。getLooper()方法是获取线程中的Looper对象,可以用来初始化Handler对象。
quit()和quitSafely()的区别在于,quit()会清空所有消息(无论延时或非延时),quitSafely()只清空延时消息,无论是调用了quit()方法还是quitSafely()方法,Looper就不再接收新的消息。即在调用了Looper的quit()或quitSafely()方法之后,消息循环就终结了,这时候再通过Handler调用sendMessage或post等方法发送消息时均返回false,线程也就结束了。

更多相关文章

  1. eclipse adb 启动失败,无法匹配android设备 的解决方案
  2. Android的两种数据存储方式分析(二)
  3. Instrumentation学习基础(一)
  4. android 异步获取图片
  5. ADB连接Android设备的三种方法
  6. 实战技巧:Android异步指南
  7. android 常用控件的使用 TextView EditTextView
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. Android(安卓)纯代码加入点击效果
  2. 四大组件_Service_AIDL_1
  3. Manifest.xml中的属性
  4. Android相机对焦问题
  5. Android类参考---Fragment
  6. Android(安卓)DataBinding使用详解
  7. Android自带的signapk.jar + .x509.pem +
  8. Android(安卓)豆瓣电影- RecyclerView
  9. Android(安卓)studio打开github上clone下
  10. Android隐藏标题栏和状态栏