我用按钮写一个应用程序,当点击按钮时,会调用以下方法:
public void click(View view) {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
因此,显然,这将在下一个输入事件到来后导致 anr。我以为这个处理输入事件的点击方法不会导致调用 InputEventReceiver 类中的 finishInputEvent 方法,但我错了,无论点击方法是否返回,仍然会调用 finishInputEvent。 InputEventReceiver 类中的 finishInputEvent 方法如下所示:
public final void finishInputEvent(InputEvent event, boolean handled) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to finish an input event but the input event "
+ "receiver has already been disposed.");
} else {
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
if (index < 0) {
Log.w(TAG, "Attempted to finish an input event that is not in progress.");
} else {
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
nativeFinishInputEvent(mReceiverPtr, seq, handled);
}
}
event.recycleIfNeededAfterDispatch();
}
我以为 nativeFinishInputEvent 会删除输入系统中队列中的一个项目,这样就不会导致 anr,但现在仍然调用 nativeFinishInputEvent,为什么仍然会导致 anr? 输入系统如何知道输入事件未被处理?
对于给定应用,所有 Android UI 事件都由单个线程处理。通过使该线程进入睡眠状态,您将阻止线程处理进一步的事件,并且系统会检测到队列中存在未处理的事件,因此 ANR。通常,您永远不应该在 UI 线程中睡觉。