Android event distribution mechanism: sit the interviewer

This article is mainly a mock interview to raise some questions and answers, and it is also a review of the entire event distribution knowledge. Readers can also try to see if these questions can be answered, well, don't talk nonsense and read the text.

Interview begins

Interviewer: Have you learned about event distribution? Talk about event distribution

Event distribution is a mechanism for distributing screen touch information to the control tree.
When we touch the screen, a series of MotionEvent event objects will be generated, and the dispatchPointerEvnet method of the view is called to distribute through the ViewRootImpl, the manager of the control tree.

Interviewer: What is the main distribution process:

In the case of the main interface of the program, the top-level view of the layout is DecorView. It will first hand over the event to the Activity, and the Activity will call the PhoneWindow method for distribution, and PhoneWindow will call the
dispatchTouchEvent method of the DecorView's parent class ViewGroup for distribution.
That is, the process of Activity->Window->ViewGroup. ViewGroup will go down to find the appropriate control and distribute the event to him.

Interviewer: Does the event necessarily pass through Activity?

no. The top-level viewGroup of our program interface, that is, the callBack of Activity is registered in decorView, so when the main interface of the program receives the event, it will first be handed over to Activity.
However, if it is another control tree, the event flow such as dialog, popupWindow, etc. will not pass through the Activity. Only the events of your own interface will pass Activity.
The onUserInteraction() method is called in the distribution method of Activity. Can you tell us what this method does?
Ok. This method will be called when the Activity receives down. It is an empty method and needs to be rewritten by the developer.
From the official comments, we can know that this method will be called when we start to interact with the Activity in any way.
The more common scenario is the screen saver: when we have not operated for a period of time, a picture will be displayed. When we start interacting with the Activity, we can cancel the screen saver in this method; in addition, if there is no operation to automatically hide the toolbar, we can use this method Let the toolbar reappear.

Interviewer: At the end, you mentioned that it will be distributed to viewGroup, so how does viewGroup distribute events?

ViewGroup processing event information is divided into three steps: interception, find child controls, and dispatch events.

There is an important rule in event distribution: an event sequence of a touch point can only be handled by one view, unless there are exceptions. So if the viewGroup consumes down events, then the child view will not receive any events.

The first step of viewGroup is to determine whether this event needs to be distributed to child views, and if so, it calls the onInterceptTouchEvent method to determine whether to intercept.
The second step is if this event is a down event, then you need to find a child control that consumes this event for him, and create a TouchTarget for him if found.
The third step is to dispatch the event. If there is a TouchTarget, it means that the child view of the consumption event sequence is found and distributed to him directly. If not, leave it to yourself.

Interviewer: You mentioned earlier that "a sequence of events at a touch point can only be handled by one view, unless there is an abnormal situation". What is the abnormal situation here? What to do if an abnormal situation occurs?

The abnormal situation here mainly has two points: 1. Intercepted by viewGroup, 2. Other situations such as interface jump occur.

When the event flow is interrupted, the viewGroup will send an ACTION_CANCEL event to the view. At this time, some state restoration work needs to be done, such as terminating the animation, restoring the view size, and so on.

Interviewer: Since it comes to the ACTION_CANCEL type, can you talk about any other event types?

In addition to ACTION_CANCEL, other event types include:

ACTION_MOVE: This event is generated when our finger slides on the screen

ACTION_UP: This event occurs when our finger is lifted

In addition, multi-finger operations are more common:

ACTION_POINTER_DOWN: When there is already a finger pressed down, another finger pressed down will generate this event

ACTION_POINTER_UP: When multiple fingers are pressed at the same time, lifting one of the fingers will generate this event.

A complete sequence of events starts from ACTION_DOWN and ends with ACTION_UP or ACTION_CANCEL.
The complete sequence of a finger starts from ACTION_DOWN/ACTION_POINTER_DOWN and ends with ACTION_UP/ACTION_POINTER_UP/ACTION_CANCEL.

Interviewer: Oh? Speaking of multiple fingers, do you know how ViewGroup accurately distributes events generated by multiple fingers to different child views?

The key to this problem lies in MotionEvent and the TouchTarget inside the ViewGroup.
Each MotionEvent contains the information of all touch points on the current screen, and an array is used internally to store the coordinate values ​​corresponding to different touch ids.

When a child view consumes the down event, the ViewGroup creates a TouchTarget for the view. This TouchTarget contains the instance of the view and the touch id. There can be multiple touch ids, that is, a view can accept multiple touch points in an event sequence.

When a MotionEvent arrives, ViewGroup will disassemble the touch point information in it, and then send them to interested child views. So as to achieve the purpose of accurately sending touch point information.

Interviewer: Does the view support multi-finger information?

View is not supported by default. When he obtains the touch point information, he does not pass in the touch point index, that is, he obtains the information of the first touch point in the internal array of MotionEvent. Multi-finger requires us to rewrite the method to support him.

Interviewer: Hmm... how does View handle touch events?

First of all, he will judge whether there is an onTouchListener, and if it does, he will call his onTouch method to handle the event. If the method returns true, then the distribution ends and returns directly. If the listener is null or the onTouch method returns false, the onTouchEvent method will be called to handle the event.
Two listeners are supported in the onTouchEvent method: onClickListener and onLongClickListener. View will call these two listeners according to different touch conditions. At the same time enter the onTouchEvent method, no matter whether the view is enable or not, as long as it is clickable, his distribution method will always return true.

To summarize: call onTouchListener first, then call onClickListener and onLongClickListener.

Interviewer: You have talked about the distribution method and return value many times before, so can you talk about the main methods and the relationship between them?

Yeah. There are three core methods: dispatchTouchEvent, onInterceptTouchEvent, and onTouchEvent.

Simply put: dispatchTouchEvent is the core distribution method, all distribution logic is executed in this method; onInterceptTouchEvent is responsible for determining whether to intercept in the viewGroup; onTouchEvent is the core method of consuming events. The viewGroup has these three methods, but the view does not have the onInterceptTouchEvent method.

viewGroup

  1. When the dispatchTouchEvent method of viewGroup receives the event message, it will first call onInterceptTouchEvent to determine whether to intercept the event.
    If intercepted, then call its own onTouchEvent method. If not, call the dispatchTouchEvent method of the child view.

  2. If the child view does not consume events, the onTouchEvent of the viewGroup itself will be called

  3. The processing result of the above steps 1 and 2 is the processing result of the dispatchTouchEvent method of the viewGroup. If there is no consumption, it returns false and returns to the onTouchEvent processing of the upper layer. If it is consumed, the distribution ends and returns true.

view

  1. The dispatchTouchEvent of the view will call onTouchEvent to handle the event by default, return true to indicate the consumption event, and return false to indicate that there is no consumption event.
  2. The result of the first step is the processing result of the dispatchTouchEvent method. If it is successfully consumed, it returns true, and if there is no consumption, it returns false and handed over to the onTouchEvent of the upper layer for processing.

Simply put, in the control tree, each viewGroup continuously distributes the view for consumption in the dispatchTouchEvent method. If the underlying view has no consumption event, it will call the onTouchEvent method of the viewGroup layer by layer to process the event.

At the same time, since Activity inherits the Window.CallBack interface, it also has dispatchTouchEvent and onTouchEvent methods:

  1. After the activity receives the touch event, it will directly distribute the touch event to the viewGroup
  2. If the dispatchTouchEvent method of the viewGroup returns false, then the onTouchEvent of the Activity will be called to handle the event
  3. The processing result of steps 1 and 2 is the processing result of the dispatchTouchEvent method of the activity and returned to the upper layer

Interviewer: It seems that you know a lot about event distribution. Have you used event distribution in practice?

Yes, yes. Give two examples.

The first requirement is to design a button block that shrinks and becomes lower in height when it is pressed, and becomes translucent when it is released, and rebounds when it is released. At this time, you can determine the event type in the onTouchEvent method of this button: down is to turn on the press animation, and up is to turn on the release animation. At the same time, pay attention to restore the state when the cancel event is received.

The second is sliding conflict. The core idea of ​​resolving sliding conflicts is to distribute sliding events to the viewGroup or internal views according to the specific situation. The main methods are external interception method and internal interception method.
The idea of ​​the external interception method is to judge the sliding situation in the viewGroup, intercept the events that conform to its own sliding, and not intercept the non-conforming events, and give it to the internal view. The idea of ​​the internal interception method requires the viewGroup to intercept all events except the down event, and then judge the sliding situation in the internal view, set a prohibition interception flag for the time that matches its own sliding situation, and cancel the mark for events that do not conform to its own sliding situation. The viewGroup is intercepted.

Interviewer: How to choose between external and internal interception methods?

In general, the external interception method does not need to rewrite the method of the sub-view, which is simpler than the internal interception method. It is recommended to use the external interception method.
But if you need to judge more touch conditions in the sub-view, you can use the internal interception method to deal with the situation in the sub-view more.
I have been talking about touch events in the previous section. Do you know how a touch event is generated from touching the screen?
Um... After the screen receives the touch information, it will hand it over to InputServiceManager for processing, and finally find the matching window through WindowManagerService, and send the touch information to viewRootImpl. After viewRootImpl is sealed and processed layer by layer, a MotionEvent event is generated. Give the view.

Interviewer: Can you specifically talk about the previous IMS processing process?

what. . This. . . Ok. . . . will not. . .

Is there anything else you want to ask?

Is it possible? . . . Give me a small thumbs up before leaving?

At last

Regarding interviews, one point I have always insisted on is: you can learn from the interview knowledge points, but you cannot learn from the answers to the interview questions . Memorizing the answers to related popular questions can fool some interviewers, but now basically it is not simply asking what is event distribution, but will give us a specific need to think about and so on. Memorizing interview questions may make us seem to have learned a lot in the short term, but in fact, we have learned nothing.

Android learning is a long road. What we have to learn is not only the superficial technology, but also the bottom layer and understand the following principles. Only in this way can we improve our competitiveness. In today's highly competitive world Foothold in.

If you also want to improve your skills, here I will also share an Android learning PDF+architecture video+interview document+source notes collected by the big guys , advanced architecture technology advanced mind map, Android development interview special materials, advanced advanced Structure information , if you want information, you can private message or comment [ Information ] Get it for free

Insert picture description here

Guess you like

Origin blog.csdn.net/A_pyf/article/details/113392655