1) Android система получает сигналы от сенсорного экрана, переводит их в более простой тип InputEvent и вызывает метод dispatchInputEvent у класса InputEventReceiver, который передаёт события Android приложению.
2) При запуске Android приложения создаётся неявный родитель для иерархии вьюшек ViewRootImpl, который является звеном между WindowManager и View, и в котором определён наследник InputEventReceiver:
final class WindowInputEventReceiver extends InputEventReceiver {
@Override
public void onInputEvent(InputEvent event) {
// добавляет в очередь новое событие InputEvent
enqueueInputEvent(...)
}
}Также в ViewRootImpl реализована очередь событий в виде связанного списка, узлом которого является QueuedInputEvent, обертка над InputEvent.
Для обработки событий используется цепочка обязанностей, реализованная наследниками InputStage: событие передаётся одному из наследников InputStage, если он не может его обработать по каким то причинам, то передаётся другому и тд. Нам интересна только иерархия View, поэтому смотрим следующий код:
final class ViewPostImeInputStage extends InputStage {
private int processPointerEvent(...) {
// передаёт touch событие в иерархию вьюшек
mView.dispatchPointerEvent(event)
}
}Механизм обработки событий можно сравнить с Looper/Handler: вместо Message - InputEvent, вместо Handler - цепочка обязанностей InputStage.
3) Корнем иерархии View является DecorView, именно здесь происходит вызов метода dispatchPointerEvent, который под капотом вызывает dispatchTouchEvent для touch события.
Метод DecorView.dispatchTouchEvent сначала пробрасывает событие в Activity.dispatchTouchEvent, вы можете переопределить данный метод, чтобы перехватить все touch события. После обработки события в Activity, оно прокидывается остальной иерархии View, пока не будет обработано.
Важно отметить, что onTouchEvent вызывается в View.dispatchTouchEvent.
Пишите в комментах ваше мнение и всем хорошего кода!
