为什么要运用Handler?
由于屏幕的改写频率是60Hz,大概16毫秒会改写一次,所以为了确保UI的流畅性,耗时操作需求在子线程中处理,子线程不能直接对UI进行更新操作。因而需求Handler在子线程发音讯给主线程来更新UI。
这里再深化一点,Android中的UI控件不是线程安全的,因而在多线程并发拜访UI的时分会导致UI控件处于不行预期的状态。Google不经过锁的机制来处理这个问题是由于:
引进锁会导致UI的操作变得复杂
引进锁会导致UI的运转功率降低
因而,Google的工程师***是经过单线程的模型来操作UI,开发者只需求经过Handler在不同线程之间切花就能够了。
概述一下Android中的音讯机制?
Android中的音讯机制主要是指Handler的运转机制。Handler是进行线程切换的要害,在主线程和子线程之间切换仅仅一种比较特别的运用情景罢了。其间音讯传递机制需求了解的东西有Message、Handler、Looper、Looper里边的MessageQueue目标。
如上图所示,我们能够把整个音讯机制看作是一条流水线。其间:
MessageQueue是传送带,担任Message行列的传送与管理
Looper是流水线的发动机,不断地把音讯从音讯行列里边取出来,交给Handler来处理
Message是每一件产品
Handler便是工人。但是这么比方不太恰当,由于发送以及终究处理Message的都是Handler
为什么在子线程中创立Handler会抛异常?
Handler的作业是依赖于Looper的,而Looper(与音讯行列)又是属于某一个线程(ThreadLocal是线程内部的数据存储类,经过它能够在指定线程中存储数据,其他线程则无法获取到),其他线程不能拜访。因而Handler便是直接跟线程是绑定在一起了。因而要运用Handler必需要确保Handler所创立的线程中有Looper目标而且发动循环。由于子线程中默许是没有Looper的,所以会报错。
正确的运用办法是:
handler=null;
newThread(newRunnable(){
privateLoopermLooper;
@Override
publicvoidrun(){
//有必要调用Looper的prepare办法为当时线程创立一个Looper目标,然后发动循环
//prepare办法中本质是给ThreadLocal目标创立了一个Looper目标
//假如当时线程已经创立过Looper目标了,那么会报错
Looper.prepare();
handler=newHandler();
//获取Looper目标
mLooper=Looper.myLooper();
//发动音讯循环
Looper.loop();
//在恰当的时分退出Looper的音讯循环,避免内存泄漏
mLooper.quit();
}
}).start();
主线程中默许是创立了Looper而且发动了音讯的循环的,因而不会报错:
应用程序的入口是ActivityThread的main办法,在这个办法里边会创立Looper,而且执行Looper的loop办法来发动音讯的循环,使得应用程序一直运转。
子线程中能够经过Handler发送音讯给主线程吗?
能够。有时分出于业务需求,主线程能够向子线程发送音讯。子线程的Handler有必要按照上述办法创立,而且相关Looper。
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com