Android音讯机制介绍
Android音讯机制中的四大概念:
-
ThreadLocal
:当前线程存储的数据仅能从当前线程取出。 -
MessageQueue
:具有时刻优先级的音讯行列。 -
Looper
:轮询音讯行列,看是否有新的音讯到来。 -
Handler
:具体处理逻辑的地方。
过程:
- 预备工作:创立
Handler
,如果是在子线程中创立,还需要调用Looper#prepare()
,在Handler
的结构函数中,会绑定其间的Looper
和MessageQueue
。 - 发送音讯:创立音讯,运用
Handler
发送。 - 进入
MessageQueue
:由于Handler
中绑定着音讯行列,所以Message
很自然的被放进音讯行列。 -
Looper
轮询音讯行列:Looper
是一个死循环,一直观察有没有新的音讯到来,之后从Message
取出绑定的Handler
,最后调用Handler
中的处理逻辑,这一切都发生在Looper
循环的线程,这也是Handler
能够在指定线程处理任务的原因。
伪代码描述的Android主线程音讯处理流程,这样会看得更明晰易懂:
// 1. 创立Handler实例,关联主线程的Looper
Handler mainHandler = new Handler(Looper.getMainLooper());
// 2. 界说音讯处理逻辑
void handleMessage(Message msg) {
int what = msg.what; // 获取音讯的what特点,表明音讯类型
Object obj = msg.obj; // 获取音讯的obj特点,携带的额外数据
// 依据音讯类型履行相应的操作
switch (what) {
case MESSAGE_TYPE_ONE:
// 处理第一种类型的音讯
break;
case MESSAGE_TYPE_TWO:
// 处理第二种类型的音讯
break;
// ...其他case处理不同的音讯类型
default:
// 默认处理逻辑
break;
}
}
// 3. 发送音讯到音讯行列
Message msg = obtainMessage(MESSAGE_TYPE_ONE); // 创立一个新音讯,并设置类型
mainHandler.sendMessage(msg); // 发送音讯到主线程的音讯行列
// 4. Handler在主线程的Looper循环中处理音讯
while (true) { // Looper的循环体
Message msg = mainHandler.getLooper().getMessageQueue().next(); // 从音讯行列中取出一个音讯
if (msg == null) {
break; // 如果音讯行列为空,退出循环,而且App进程会完毕
}
handleMessage(msg); // 调用handleMessage办法处理音讯
}
// 5. 音讯处理完成
// handleMessage办法中的代码会依据音讯类型履行相应的逻辑
Android中为什么主线程不会由于Looper.loop()里的死循环卡死?
Android中为什么主线程不会由于Looper.loop()里的死循环卡死? – Gityuan的回答 – 知乎 www.zhihu.com/question/34…
简略的总结来说:主线程也不过是运行在运用进程里面的,但实际上对于CPU来说这些进程,线程,都是一片片代码块,按照指令去履行,死循环的规划为了确保主线程能够一直存活,不会在运行一段时刻后主动退出,这样App就不会无故完毕掉了,而真实导致主线程卡死的操作是在回调办法如onCreate
、onStart
、onResume
等中履行时刻过长。这些长时刻的操作会导致界面掉帧,乃至触发运用程序无响应 ANR。然而,Looper.loop()
自身并不会导致运用卡死。当没有音讯需要处理时,主线程会休眠,等候新音讯的到来,不会过多占用CPU资源。
子线程必定不能更新ui么?什么时候能够?什么时候不能够。
子线程更新UI的规则:
不能够:
- 直接从子线程调用UI组件的办法,如
TextView.setText()
,Button.setEnabled()
等,这些都是不允许的。 - 在子线程中直接操作布局或者视图层次结构也是不允许的。
能够:
- 经过
Handler
将音讯发送到主线程的音讯行列中,然后在主线程的Handler
中处理音讯并更新UI。 - 运用
AsyncTask
类,它允许在后台线程中履行耗时操作,然后在完成时将成果发布到主线程以更新UI。 - 运用
LiveData
和ViewModel
,这些是Android架构组件的一部分,它们能够在后台线程中进行数据加载,然后在主线程中观察和更新UI。 - 运用
runOnUiThread()
办法,这是Activity
类的一个办法,它允许你将一个Runnable目标发布到主线程的音讯行列中,并在主线程中履行。
Activity的生命周期是怎么完成在死循环体外能够履行起来的?
实际上Activity的生命周期还是是经过Android的音讯机制和Handler来完成的,依托主线程的Looper.loop,当收到不同Message时则选用相应措施;比方收到msg=H.LAUNCH_ACTIVITY,则调用ActivityThread.handleLaunchActivity()办法,终究会经过反射机制,创立Activity实例,然后再履行Activity.onCreate()等办法;再比方收到msg=H.PAUSE_ACTIVITY,则调用ActivityThread.handlePauseActivity()办法,终究会履行Activity.onPause()等办法。
结合简略流程图和看以下的伪代码,你就更明晰的知道,Activity生命周期和Handle之间的一些纤细联系,还有AMS在其间所做的一些处理:
// 伪代码表明的Android体系类和办法
class ActivityThread {
private Looper mainLooper;
private Handler mainHandler;
// 初始化主线程的Looper和Handler
function initLooperAndHandler() {
mainLooper = Looper.prepareMainLooper();
mainHandler = new Handler(mainLooper) {
override function handleMessage(Message msg) {
// 依据音讯的内容履行不同的生命周期操作
switch (msg.what) {
case MSG_START_ACTIVITY:
startActivity(msg.obj); // msg.obj包含Activity的相关信息
break;
case MSG_RESUME_ACTIVITY:
resumeActivity(id); // id是Activity的标识
break;
case MSG_PAUSE_ACTIVITY:
pauseActivity(id);
break;
case MSG_STOP_ACTIVITY:
stopActivity(id);
break;
case MSG_DESTROY_ACTIVITY:
destroyActivity(id);
break;
// 其他音讯处理...
}
}
}
}
// 启动Activity
function startActivity(activityInfo) {
// 创立Activity实例并调用onCreate等生命周期办法
activity = createActivityInstance(activityInfo)
activity.onCreate()
// ...
}
// 恢复Activity
function resumeActivity(id) {
activity = findActivityById(id)
activity.onResume()
// ...
}
// 暂停Activity
function pauseActivity(id) {
activity = findActivityById(id)
activity.onPause()
// ...
}
// 停止Activity
function stopActivity(id) {
activity = findActivityById(id)
activity.onStop()
// ...
}
// 毁掉Activity
function destroyActivity(id) {
activity = findActivityById(id)
activity.onDestroy()
// ...
}
}
// 在Application的onCreate办法中初始化ActivityThread
ActivityThread.mainThread.initLooperAndHandler();
// 伪代码表明的Activity类
class Activity {
// 重写生命周期回调办法
function onCreate() {
// 初始化UI和数据
}
function onStart() {
// Activity开端变得可见
}
function onResume() {
// Activity预备交互
}
function onPause() {
// Activity暂停,不再交互
}
function onStop() {
// Activity不再可见
}
function onDestroy() {
// 整理资源,Activity即将被毁掉
}
}
// 伪代码表明的AMS( Activity Manager Service )发送音讯给ActivityThread
class AMS {
function sendMessageToActivityThread(msg) {
// 经过Binder IPC机制发送音讯到ActivityThread的主线程Handler
ActivityThread.mainHandler.sendMessage(msg);
}
}
// AMS依据不同的事件向ActivityThread发送音讯
AMS.sendMessageToActivityThread(MSG_START_ACTIVITY);
AMS.sendMessageToActivityThread(MSG_RESUME_ACTIVITY);
AMS.sendMessageToActivityThread(MSG_PAUSE_ACTIVITY);
AMS.sendMessageToActivityThread(MSG_STOP_ACTIVITY);
AMS.sendMessageToActivityThread(MSG_DESTROY_ACTIVITY);
以后每两天之内更新一道Android常见的面试题,以自己的角度去通俗简略易懂方式去说,不深化源码但讲基本原理,以伪代码为中心;如果你比较想问什么问题,能够评论。