Android Development-Analyze ViewGroup, view's event distribution mechanism, and combine responsibility chain model

Source: Internet
Author: User

Introduced

Previous blog responsibility chain/Responsibility chain model (Chain of Responsibility) analytical understanding and application in Android
This paper introduces the responsibility chain model as the basis of understanding the view event distribution mechanism.
To apply the structural analysis of the responsibility chain pattern, when our fingers are clicked or slid on the screen, it is an event, each view or viewgroup that is displayed on the screen is the duty object, they pass the event through the views hierarchy in Android, and the events are routed through layers until the responsible object processes the consumed event. or no duty object handling causes the event to disappear.

Key Concept Introduction

To understand event distribution for view, take a look at a few key concepts

Motionevent

When the finger touches the screen, the resulting sequence of events is comprised of the following three types of events.
1. Action_down: Finger Press the screen
2. Action_move: The finger moves on the screen
3. ACTION_UP: Finger lifted from the screen
For example, a simple screen touch action triggers a series of touch events: ACTION_DOWN->ACTION_MOVE->...->ACTION_MOVE->ACTION_UP
For this event distribution mechanism in Android, this event refers to Motionevent. The distribution of the view's events is also a distribution operation to Motionevent. You can use GETRAWX and Getrawy to get the horizontal ordinate of events relative to the upper-left corner of the screen. Gets the horizontal ordinate of the event relative to the upper-left corner of the current view through Getx () and Gety ().

Important method
    1. public boolean dispatchtouchevent (motionevent ev)

      This is a way to distribute the event. If an event is passed to the current view, the current view must call the method. The return type for Dispatchtouchevent is Boolean, and the return result indicates whether the event is consumed, and if true, indicates that the view has been consumed and will not continue to pass down.
        

    2. public boolean onintercepttouchevent (motionevent ev)

      This method exists in the ViewGroup class, and there is no such method for the view class. Indicates whether to intercept an event, ViewGroup if an event is successfully intercepted, then the event is not passed down. For the same event sequence, if the current view successfully intercepts the event, the method will not be called again for subsequent series of events. The returned result indicates whether to intercept the current event and return false by default. Because a view is already at its lowest level, it does not have child controls, so there is no such method.
        

    3. public boolean ontouchevent (Motionevent event)

      This method is called by Dispatchtouchevent to handle the event and is used to indicate whether the current event is consumed by the returned result. If the current event is not consumed, the current view will not receive the event again for the same sequence of events.

Part of the above is from "Android Development Art exploration"

Code experiment

To verify and understand the actual running state, rewrite the view and ViewGroup key methods to print the method call.

Code

Inherit the view override method and add the result to print.
Note: View is a child control, there is no inner child control, so the incoming event is handled on the view, and there is no event to intercept the child control, so there is no onInterceptTouchEvent method

 Public  class MyView extends View {     Public MyView(Context context) {Super(context); } Public MyView(context context, AttributeSet attrs) {Super(context, attrs); } Public MyView(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); }@Override     Public Boolean dispatchtouchevent(Motionevent ev) {Booleanresult=Super. dispatchtouchevent (EV); LOGGER.D ("result="+result+"info="+motionevent.actiontostring (Ev.getaction ()));returnResult }@Override     Public Boolean ontouchevent(Motionevent event) {Booleanresult=Super. Ontouchevent (event); LOGGER.D ("result="+result+"info="+motionevent.actiontostring (Event.getaction ()));returnResult }}

Inherit the ViewGroup override method and add the result to print.
Note: ViewGroup does not implement the OnLayout placement control position, so inheritance linearlayout, does not affect the distribution

 Public  class myviewgroup extends linearlayout {     Public Myviewgroup(Context context) {Super(context); } Public Myviewgroup(context context, AttributeSet attrs) {Super(context, attrs); } Public Myviewgroup(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); }@Override     Public Boolean dispatchtouchevent(Motionevent ev) {Booleanresult=Super. dispatchtouchevent (EV); LOGGER.D ("result="+result+"info="+motionevent.actiontostring (Ev.getaction ()));returnResult }@Override     Public Boolean ontouchevent(Motionevent event) {Booleanresult=Super. Ontouchevent (event); LOGGER.D ("result="+result+"info="+motionevent.actiontostring (Event.getaction ()));returnResult }@Override     Public Boolean onintercepttouchevent(Motionevent ev) {Booleanresult=Super. onintercepttouchevent (EV); LOGGER.D ("result="+result+"info="+motionevent.actiontostring (Ev.getaction ()));returnResult }}

Finally, the two controls are added to the layout file.

<com. Demo. Licola. Httpdemo. View. MyviewgroupAndroid:layout_width="200DP"android:layout_height="200DP"Android:id="@+id/ll_group"Android:background="@color/saffron"> <com. Demo. Licola. Httpdemo. View. MyViewAndroid:layout_width="100DP"android:layout_height="100DP"Android:id="@+id/view_child"Android:background="@color/coloraccent"/> </com. Demo. Licola. Httpdemo. View. Myviewgroup>
Test run directly

After running the above code first, you can see two color blocks. Use your phone to click on the Myviewgroup child control MyView.

Believe me, no matter how the swipe or click is the same result, the following will analyze the cause of this situation.

Analysis:
    1. Finger Click in Myviewgroup method onintercepttouchevent start call to determine whether to intercept this click event.
      ViewGroup2717 Line code, the source of the ViewGroup default is not to intercept the event:
publicbooleanonInterceptTouchEvent(MotionEvent ev) {        returnfalse;    }
    1. Because ViewGroup does not intercept the Click event, the event starts distributing, and the child control view has an opportunity to get the event, calling the internal two methods to handle the event, because I do not do any processing by default, and view does not handle the event and returns false.
    2. Finally, there is no control response because of the down event. If the current event is not consumed, the current view will not receive the event again for the same sequence of events.
    3. So the finger slides after touching the screen, and the view will not accept the move event. So the finger how to swipe no other log results print. Unless you lift, press to generate a new event and see the same print results.
To have a child control respond to an event

Modify the code to add a click event to the view, i.e. use setOnClickListener simple processing.
Then click on the finger to lift it quickly, or the print result is too much.

Analysis: Generate Click events, child control ontouchevent can handle events, get down events, while affecting ViewGroup parent control dispatchtouchevent return ture can be distributed downward, subsequent up events are also passed in.

To have the parent control intercept events

On the original basis, the code is modified again to return true to the Onintercepttouchevent method of the ViewGroup parent control, which represents the interception event. Then add a click-Listen callback to ViewGroup setOnClickListener .

Analysis: With the foundation above, here is what to say, because the parent control intercepts the event, and can respond to the event, all the events are sent to the ViewGroup.

Summarize

Through the results of the above 3 experiments, we can probably have a basic understanding of the distribution of VIEWGOURP events.
So through the abstraction of the key implementation of source code, you can have the following approximate processing logic.

The following logic is in the ViewGroup:

publicbooleandispatchTouchEvent(MotionEvent ev) {        boolean consume =false;//默认不处理        if (onInterceptTouchEvent(ev)){//首先判断是否拦截            consume=onTouchEvent(ev);//看是否能够处理        }else {        //如果不拦截,遍历子控件,这里省略掉        //调用子控件的分发方法,下发事件。            consume=getChildView.dispatchTouchEvent(ev);        }        return consume;    }
Analysis of the mode of responsibility chain integration

In my previous blog, I introduced the analysis of the responsibility chain model, which was analyzed by the idea of the model.

You can draw a UML diagram like this:

Of course, this is a simple drawing, the actual will be much more complex, and the view and Viewgorup using the design pattern combination of thought constructs.

    • Cilent: Represents the object that made the request, which should correspond to activity.
    • Viewhandler: The interior is held as an array of successors, using a traversal from the last one when used. The Dispatchtouchevent method represents a unified event request method
    • View and Viewgourp: Are actual implementations of the responsibility class, internally by invoking other methods to determine whether the request event can be handled.

      Structure of the chain:
      It is obvious that the structure of the chain is assembled in the Viewhandler, and the inner chain is realized. Ontouchevent and onintercepttouchevent all affect the construction of the chain. Dynamic generation of responsibility chains.

Summary of Viewgroup/view's event distribution mechanism

Finally, some conclusions are put forward to give you some tips and summaries on the distribution of events. Maybe I'll use it for the interview.
Tip: ViewGroup inherits the view on the inheritance relationship, so you can use view to refer to ViewGroup later. For specific reasons, Google for yourself.

    1. The same sequence of events is calculated from the finger touch screen beginning, and the finger leaves the screen end. That is, the down event starts + an indefinite number of move event +up events
    2. Normally, an event sequence can be intercepted and consumed by only one view. Because once a view intercepts this event, all events in the same sequence of events are handed to it directly, so events in the same event sequence cannot be distributed to two view simultaneous processing.

This is the main problem we encounter when dealing with some nesting slips. The child control intercepts the event, and when the view does not want to handle the slide event, it can only discard the event and not pass it on to the parent view. This is why sliding nested parent-child controls are not flowing in the same direction. The good news when the appearance of Nestedscrollview a good solution to this problem.

    1. Once a view has decided to intercept an event, its onintercepttouchevent will not be called again, so subsequent events are addressed directly to it and no longer asked whether or not to intercept. The printed results on this can be verified.
    2. Once a view starts processing an event, if it does not consume the down event (Ontouchevent returns false) then no other events in the same sequence of events will be handed over to it, and the event is re-disposed to the parent view. That is, the ontouchevent of the parent view is called. That is, once the event is given to view and it does not consume the event, the subsequent sequence of events is no longer distributed to it, and the parent control begins to attempt to handle the event. This can be verified in the first test result diagram.
    3. If the view does not consume events other than down, the click event disappears, and the ontouchevent of the parent view is not called, and the current view can continue to receive subsequent events, and eventually these vanishing click events are passed to activity processing.
    4. ViewGroup does not intercept any events by default, see above for details.
    5. The real view does not have a onintercepttouchevent method, and once an event is sent to it, its ontouchevent is called.
    6. The onclick will occur if the current view is clickable, and it receives the down and up events.
    7. The event delivery process is delivered from within. That is, the event is always first passed to the parent view, and then the parent view decides to distribute. The Requestdisallowintercepttouchevent method allows you to intervene in the child view's event distribution process for the parent view, except for the down event.
Summarize
    • This part of the content from the "Android Development Art Exploration", the book contains specific source code analysis, interested can go to see.
    • This paper mainly discusses some of the conclusions in the experiment, and proposes a solution to the sliding conflict using Nestedscrollview, and many controls in the Android source code implement the Nestedscrollview method.
    • This paper also analyzes the view event distribution mechanism with the responsibility chain model. Help understand the principle of implementation through a higher level of abstract analysis. Combined with some source code analysis, and did not fall into the source.

Android Development-Analyze ViewGroup, view's event distribution mechanism, combine responsibility chain mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.