Android——Analysis of distribution processing flow of key event KeyEvent

foreword

This time I plan to sort out the distribution process of the key click event KeyEvent in Android Tv. When it comes to the click event mechanism, the online information is very complete, such as the three major processes of distribution, interception, and processing; or dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent; or return true to indicate consumption, and return false to not process; there is also a saying The whole process is a U-shaped distribution process. The general manager issues tasks to employees to process feedback and the like. The predecessors have already sorted out the dry goods for us, and they are also writing as popular and understandable as possible.

But the topic of today's article is: KeyEvent distribution process

To put it plainly: the process of dispatching and processing the click event of the remote control button on the TV, maybe you haven't realized it yet. Think about it, the mobile phone is a touch screen click event, while the remote control is a button click event. The distribution and processing mechanisms of the two types of events are naturally different. Confusing these two types of event distribution mechanisms.

The simplest difference is that in Tv development, dispatchTouchEvent, onInterceptTouchEvent, and onTouchEvent are no longer used for dispatchTouchEvent, onInterceptTouchEvent, and onTouchEvent like touch-screen mobile phones.

process

This time, we only sort out the distribution process of KeyEvent in a View tree. To put it simply, you click a button on the remote control in a certain Activity interface, and then how does the button event behave in the current Activity? distributed processing.
insert image description here
The main methods and classes involved in the flowchart:

(PhoneWindow$)DecorView -> dispatchKeyEvent()
Activity -> dispatchKeyEvent()
ViewGroup -> dispatchKeyEvent()
View -> dispatchKeyEvent()
KeyEvent -> dispatch()
View -> onKeyDown/Up()

The acquisition, distribution, and processing of key events at the hardware layer and framework layer are too esoteric to understand. A part of the event distribution process in the application layer has not yet been thoroughly understood. This time, the distribution process within a View tree is sorted out.

Process Analysis

ps: When we click a remote control button in an Activity interface, there will be two KeyEvents, Action_Down and Action_Up, for distribution processing. The distribution process is the same, and the difference is that they are finally handed over to the onKeyDown or onKeyUp of the Activity or View for processing.

distribution process

When a KeyEvent event is received, it is first handed over to (PhoneWindow$)DecorView's dispatchKeyEvent() for distribution, and DecorView will call Activity's dispatchKeyEvent(), and then hand it over to the Activity for further distribution.
insert image description here
Activity will first obtain the PhoneWindow object, then call PhoneWindow's superDispatchKeyEvent(), PhoneWindow will call DecorView's superDispatchKeyEvent(), and DecorView will call super.dispatchKeyEvent() to distribute the event to the parent class. DecorView inherits from FrameLayout, but FrameLayout dispatchKeyEvent() is not implemented, so it is actually handed over to dispatchKeyEvent() of ViewGroup for distribution.
insert image description hereinsert image description hereinsert image description here
1. I still don't understand the logic of ViewGroup distribution, but generally know that ViewGroup recursively finds the sub-View of the current focus, and sends the event to the dispatchKeyEvent() distribution of the focused sub-View. How to recursively find this part of the code is to be studied.

2. The above is the distribution process of a KeyEvent event. It is different from the touch screen mobile phone event transmission. If you do not rewrite the relevant distribution method of the above distribution event related classes, a KeyEvent event will definitely be distributed from the top DecorView to The specific sub-View, because it does not have an operation that is intercepted at a certain layer like onInterceptTouchEvent.

processing flow

ps: There are only two places to process the KeyEvent event, one is the Activity, and the other is the specific View. ViewGroup is only responsible for distribution and does not consume events. Same as TouchEvent, returning true means the event has been consumed, and returning false means the event is still there.

When the KeyEvent event is assigned to the dispatchKeyEvent() of the specific sub-View, the View will first check whether the OnKeyListener listener is set, and if so, call back the OnKeyListener.onKey() method to handle the event.
insert image description hereIf View does not set OnKeyListener or onKey() returns false, View will call back View's own onKeyDown/Up() to handle the event by calling the dispatch() method of KeyEvent.
insert image description here
If the View's onKeyUp method is not rewritten, and the event is the Action_Up event of the ok (confirmation) button, the View will check to see if there is an OnClickListener listener set, and then call OnClickListener.onClick() to consume the event, pay attention to consumption , that is to say, if there is an OnClickListener listener set for the View, and the event is not consumed in the above two steps, it must be consumed in onClick(). Although OnClickListener.onClick() does not return boolean Value, but when View dispatches the event to onClick in the internal dispatchKeyEvent(), it has returned true by default to indicate that the event has been consumed.
insert image description here
If the View does not handle the event, that is, neither OnKeyListener nor OnClickListener is set, and onKeyDown/Up() returns false, it will return to the original way of dispatching the event to inform the Activity that the current event has not been consumed, and the Activity receives the ViewGroup When the false message is returned, it will call the Activity's own onKeyDown/Up() event through KeyEvent's dispatch(), and hand over the event to the Activity itself for processing. This is our common way to override onKeyDown/Up() in Activity to handle click events, but note that the processing here is the last to be received, so it is very likely that the event will be consumed before it reaches here.

summary

insert image description here
The overall distribution processing flow is shown in the figure above (the hand is shaking, otherwise it is a straight line). We can summarize some important points:

1. If you don’t know much about DecorView, you can only focus on the points we often touch, such as Activity, ViewGroup, View, based on this:

2. Event distribution: Activity gets the KeyEvent event first, but there is no way to intercept the processing by itself (you must have objections here, I will explain it below), and then distribute the event to ViewGroup, and ViewGroup can only recursively distribute to For sub-Views, events will never be consumed in ViewGroup. Finally, sub-Views receive events, the distribution process ends, and event processing begins.

3. Event processing: Only Activity and View can handle events. View can choose whether to handle events in OnKeyListener, OnClickListener or onKeyDown/Up() according to the situation. Activity can only handle events in onKeyDown/Up().

4. Event processing can be summed up in four places, which are arranged in the following order: View's OnKeyListener.onKey(), onKeyDown/Up(), OnClickListener.onClick(), Activity's onKeyDown/Up(). Once somewhere in the four places, the event is consumed, that is, true is returned, and the event will not be passed to the subsequent processing methods.

Why do I say that Activity cannot intercept events and handle them by itself?

In the TouchEvent click event mechanism of the touch screen, we can stop the distribution of the interception event and process the event by ourselves by rewriting onInterceptTouchEvent() to return true, but there is no such method in KeyEvent, so if dispatchKeyEvent() is only used for event distribution The event processing is done in onKeyDwon/Up, onKey(), onClick(). In this case, the Activity really has no way to intercept the event distribution and hand it over to its own onKeyDown/Up().

But who stipulates that dispatchKeyEvent() can only do event delivery, so in theory, according to the standard, Activity cannot intercept event distribution and handle it by itself, but in actual programming, I often encounter people rewriting dispatchKeyEvent() in Activity to handle events , and then let it return true or false to stop the distribution of events.

scenes to be used

The distribution and processing process of the KeyEvent event generally needs to know how it goes. If you are interested, you can go to the source code again, and then draw the flow chart yourself to understand it better. First sort out the distribution processing flow, we will know how to use it, how to rewrite the distribution processing method, the following will talk about some usage scenarios:

1. Rewrite dispatchKeyEvent() in Activity - the most commonly used

Take a chestnut:
insert image description here
This is very common in TV development, often rewrite dispatchKeyEvent() in Activity, and then either pre-process some work, or intercept specific keys.

Can you understand the above code? If you already know that this code intercepts the left and right buttons, do you know the functions of various returns, why there are return true, return false, and return super.dispatchKeyEvent()?

Let me talk about the conclusion first: the return true and return false here can both play the role of key interception, that is, the child View will not receive the distribution or processing of events, and the onKeyDown/Up() of the Activity will not receive any messages.

To understand this, you must first figure out what return is. Return means return. Under what circumstances does it need to return? Doesn’t it mean that the method that calls you needs you to give feedback, so the message of return is for the caller at the upper level Yes, so return will only affect the behavior of the caller at the upper level. The call to Activity.dispatchKeyEvent() is in the dispatchKeyEvent() of DecorView, as shown in the figure below:
insert image description here
So, since the Activity returns true or false, it only affects the behavior of DecorView, so why can it play the role of intercepting event distribution?

This is because the event distribution logic is actually implemented in dispatchKeyEvent() of Activity.java. If you rewrite the dispatchKeyEvent() method of Activity, then the program will execute the dispatchKeyEvent() you wrote according to the characteristics of Java. The method of the base class Activity.java will not be executed, so you do not implement the event distribution logic yourself in the rewritten method, and of course the event will stop distribution. This is why the event will continue to be distributed when super.dispatchKeyEvent() is returned, because it will eventually call the dispatchKeyEvent() method of the base class Activity.java to execute the logic of event distribution.

Since returning true or false in the Activity means interception, is there any difference?

Of course, because it will affect the behavior of DecorView. For example, when we click the arrow keys on the remote control, the focus on the interface will follow. This part of the logic is actually implemented in the upper-level caller of DecorView. If the Activity returns true, It will cause DecorView to return true, then the upper level will stop the focus movement according to the result of DecorView returning true. This is our common principle of rewriting dispatchKeyEvent() in Activity to return true to stop focus movement. Then, if Activity returns false, DecorView also returns false, then the upper level will continue to execute the logic of focus movement, and the effect shown is that the focus on the interface will still move, but it will not trigger the activation of Activity and View. Event distribution and processing methods, because they have been intercepted by Activity.

Finally, there is another question, will rewriting dispatchKeyEvent() in View or ViewGroup have the same effect as Activity?

The meaning of return true or false or super is still the same, but there is a hierarchy to understand. Upper layer: Activity, middle layer: ViewGroup, lower layer: View.

No matter at which layer dispatchKeyEvent() is rewritten, if it returns true or false, then its lower layer including its own layer will not receive the event distribution processing, but its upper layer will receive it. Because the interception effect only acts on this layer and the lower layer, and the upper layer will only be affected according to the value you return.

For example, if true is returned in ViewGroup, the onKeyDown/Up() of Activity will not be triggered because it is consumed; if false is returned, the event will be handled by Activity. But regardless of returning true or false, the sub-View's dispatchKeyEvent(), various onClick() and other event processing methods will not be triggered.

2. Rewrite onKeyDown/Up() in Activity - the most commonly used

The fact that the event can come here means that it is not consumed by the child View. This is the last place to process the event in the layer we can touch. And even if we do some work here, it doesn't have to return true. For example, if it is an arrow key event, if you return true here, it will affect the movement of the superior to stop the focus, so it depends on the situation.

3. Set OnKeyListener() for a specific View (such as TextView) - commonly used

This should be quite common, get the object of a certain control in the Activity, then set the click event listener, and then do something.

4. Set OnClickListener() for a specific View (such as Button) - commonly used

This should be more common, setOnClickListener, many scenarios need to monitor the click event of a control, to be clear: the listener listens to the Action_Up event of the ok (confirmation) button.

To sum up:

dispatchKeyEvent(): It is more common to rewrite this method in the Activity or custom ViewGroup type control. Sometimes it is necessary to pre-process some work before the event starts to be distributed, and sometimes it is necessary to intercept specific keys. Pay attention to the interception The scope and the role of various return values ​​are enough. Usually, return super will be included, because we don't need to intercept all keys, and some keys still need to continue to be distributed, because the Android system handles many special keys by default.

Clarify the meaning of super. The rewritten method will generally perform the default logic work, such as dispatchKeyEvent to execute the distribution of events. When rewriting, pay attention to whether you still need to use the logic of the parent class.

Remaining problem

1. There will be two events of Action_Down and Action_Up every time a button is clicked. At present, in such a scenario, when Activity B is opened from Activity A, Action_Down and Action_Up will be distributed and processed in Activity A, and then Action_Up will be distributed and processed in Activity B. .

The original idea is that Activity A passes the Action_Up event to Activity B for processing, but in Activity A consumes Action_Up first and then returns true, and found that Activity B will still redistribute the Action_Up event. Therefore, we still don't know much about how the KeyEvent event is distributed in the two Activities. This part of the content should be in ViewRootImpl and PhoneWindow. The next article is planned to sort out this part of the content.

2. The most important and troublesome thing in TV development is the focus problem. After clicking the arrow keys on the remote control, you can control the movement of the focus. Sometimes you need to control the focus according to your needs. For example, what we often do is to rewrite when the focus reaches the boundary. Return true in dispatchKeyEvent to stop the movement of the focus, why can this be done? In fact, this part of the content is also in the dispatchKeyEvent of DecorView. DecorView has extracted a single class in the high-end SDK. If you can’t find it, then go to PhoneWindow to find it. In the old SDK, DecorView is an internal class of PhoneWindow. This part The content is also saved for next time to sort out together.

Original link: Android key event KeyEvent distribution processing flow analysis

Guess you like

Origin blog.csdn.net/u012230055/article/details/103824930