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.
81 lines
2.4 KiB
81 lines
2.4 KiB
5 years ago
|
---
|
||
|
主线程为什么没有 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 循环,而是因为主线程有耗时任务
|