You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
android-notes/blogs/Android/Framework/Interview/线程通信相关/主线程为什么没有 ANR.md

81 lines
2.4 KiB

---
主线程为什么没有 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 循环,而是因为主线程有耗时任务