Android HandlerThread的使用及原理详解
一、handlerthread的含义
handlerthread能够新建拥有looper的线程。这个looper能够用来新建其他的handler。(线程中的looper)需要注意的是,新建的时候需要被回调。
二、handlerthread的用法
一般情况下,我们会经常用handler在子线程中更新ui线程,那是因为在主线程中有looper循环,而handlerthread新建拥有looper的子线程又有什么用呢?
必然是执行耗时操作。举个例子,数据实时更新,我们每10秒需要切换一下显示的数据,如果我们将这种长时间的反复调用操作放到ui线程中,虽说可以执行,但是这样的操作多了之后,很容易会让ui线程卡顿甚至崩溃。
于是,就必须在子线程中调用这些了。
handlerthread继承自thread,一般适应的场景,便是集thread和handler之所长,适用于会长时间在后台运行,并且间隔时间内(或适当情况下)会调用的情况,比如上面所说的实时更新。
三、实现每2秒更新一下ui
public class mainactivity extends appcompatactivity { private textview tvmain; private handlerthread mhandlerthread; //子线程中的handler private handler mthreadhandler; //ui线程中的handler private handler mmainhandler = new handler(); //以防退出界面后handler还在执行 private boolean isupdateinfo; //用以表示该handler的常熟 private static final int msg_update_info = 0x110; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); tvmain = (textview) findviewbyid(r.id.tv_main); initthread(); } private void initthread() { mhandlerthread = new handlerthread("check-message-coming"); mhandlerthread.start(); mthreadhandler = new handler(mhandlerthread.getlooper()) { @override public void handlemessage(message msg) { update();//模拟数据更新 if (isupdateinfo) mthreadhandler.sendemptymessage(msg_update_info); } }; } private void update() { try { //模拟耗时 thread.sleep(2000); mmainhandler.post(new runnable() { @override public void run() { string result = "每隔2秒更新一下数据:"; result += math.random(); tvmain.settext(result); } }); } catch (interruptedexception e) { e.printstacktrace(); } } @override protected void onresume() { super.onresume(); //开始查询 isupdateinfo = true; mthreadhandler.sendemptymessage(msg_update_info); } @override protected void onpause() { super.onpause(); //停止查询 //以防退出界面后handler还在执行 isupdateinfo = false; mthreadhandler.removemessages(msg_update_info); } @override protected void ondestroy() { super.ondestroy(); //释放资源 mhandlerthread.quit(); } }
四、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(); } process.setthreadpriority(mpriority); onlooperprepared(); looper.loop(); mtid = -1; } 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; } 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; } }
首先我们可以看到handlerthread继承自thread,因此在run()中的逻辑都是在子线程中运行的。
接下来就是两个关键的方法,run()和getlooper():
run()中可以看到是很简单的创建looper以及让looper工作的逻辑。
run()里面当mlooper创建完成后有个notifyall(),getlooper()中有个wait(),这有什么用呢?因为的mlooper在一个线程中执行创建,而我们的handler是在ui线程中调用getlooper()初始化的。
也就是说,我们必须等到mlooper创建完成,才能正确的返回。getlooper();wait(),notify()就是为了解决这两个线程的同步问题。
推荐阅读
-
Android HandlerThread的使用及原理详解
-
Android性能优化之LeakCanary的使用及项目中的实际运用
-
python如何使用urllib/urllib2访问http的GET及POST详解
-
Dynamic和Var的区别及dynamic使用详解
-
在Android中使用WebSocket实现消息通信的方法详解
-
PHP的缓存你了解多少?深入探索PHP缓存原理及使用_PHP教程
-
php语言中使用json的技巧及json的实现代码详解,json详解
-
Android Studio 中的 gradle 介绍及build.gradle配置文件详解
-
PHP中的静态变量及static静态变量使用详解
-
详解Android aidl的使用方法