diff --git a/blogs/Android/Framework/Interview/线程通信相关/主线程为什么没有 ANR.md b/blogs/Android/Framework/Interview/线程通信相关/主线程为什么没有 ANR.md new file mode 100644 index 0000000..5cb16ff --- /dev/null +++ b/blogs/Android/Framework/Interview/线程通信相关/主线程为什么没有 ANR.md @@ -0,0 +1,81 @@ +--- +主线程为什么没有 ANR? +--- + +1. 了解 ANR 的触发的原理 +2. 了解应用大致启动流程 +3. 了解线程的消息循环机制 +4. 了解应用和系统服务通信过程 + +#### ANR 是什么? + +```java +final void appNotResponding(ProcessRecord app, ...){ + Message msg = Message.obtain(); + msg.what = SHOW_NOT_RESPONDING_MSG; + mUiHandler.sendMessage(msg); +} +// SystemService 进程 +Dialog d = new AppNotRespondingDialog(...); +d.show(); +``` + +ANR 场景有哪些? + +1. Service Timeout +2. BroadcastQueue Timeout +3. ContentProvider Timeout +4. InputDispatching Timeout + +以 Service 为例,看一下 ANR 是怎么触发的? + +```java +void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInfg){ + bumpServiceExecutingLocked(r, execInFg, "create"); + app.thread.scheduleCreateService(r, r.serviceInfo, ...); +} +void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why){ + scheduleServiceTimeoutLocked(r.app); +} +void scheduleServiceTimeoutLocked(ProcessRecord proc){ + long now = SystemClock.uptimeMillis(); + Message msg = mAm.mHandler.obtainMessage(SERVICE_TIMEOUT_MSG); + mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT); +} +void serviceTimeout(ProcessRecord proc){ + mAm.appNotResponding(proc, ...); +} +// 应用端处理 Service 请求 +private void handleCreateService(CreateServiceData data) { + service = (Service)cl.loadClass(data.info.name).newInstance(); + ContextImpl context = ContextImpl.createAppContext(this, packageInfo); + Application app = packageInfo.makeApplication(false, mInstrumentation); + service.attach(context, this, data.info.name, data.token, ...); + service.onCreate(); + ActivityManagerNative.getDefault().serviceDoneExecuting(...); +} +private void serviceDoneExecutingLocked(ServiceRecord r, ...){ + mAm.mHandler.removeMessage(SERVICE_TIMEOUT_MSG, r.app); +} +``` + +往主线程发消息: + +```java +@Override +void scheduleLaunchActivity(Intent intent, IBinder token, ...){ + sendMessage(H.LAUNCH_ACTIVITY, r); +} +void scheduleCreateService(IBinder token, ...){ + sendMessage(H.CREATE_SERVICE, s); +} +void scheduleReceiver(Intent intent, ActivityInfo info, ...){ + sendMessage(H.RECEIVER, r); +} +``` + +#### 总结 + +1. ANR 是应用没有在规定的时间内完成 AMS 指定的任务导致的 +2. AMS 请求调用应用端 binder 线程,再丢消息去唤醒主线程来处理 +3. ANR 不是因为主线程 loop 循环,而是因为主线程有耗时任务 \ No newline at end of file