Event Distribution Source Flow _ event distribution from click Screen to event handling

Source: Internet
Author: User
Tags prev
Distributing source flow from the event-clicked screen to event-handling events

Let's get a picture first.

How to print it, code first.
Thread.dumpstack ();
Execute this method in the Dispatchtouchevent (Motionevent event) method

Through the above methods, you can print out from the click Screen to execute Dispatchtouchevent (Motionevent event) of the implementation process, feeling after the analysis no longer need to go to a way to find a direct according to the flow of the

Welcome to the bottom of the big guy hit the bottom of the face of New me

The first execution is Zygoteinit's main () method feels like it's time to start learning Java, and the Android system starts with the main method.

Always thought there was no main method in the Android world.

Zygoteinit

public static void Main (String argv[]) {
    try {
        ...
    } catch (Methodandargscaller caller) {
        caller.run (); c4/>} catch (RuntimeException ex) {
        closeserversocket ();
        Throw ex;
    }
}

The bottom of the thing dare not speak, we look directly at the process

Zygoteinit$methodandargscaller.run

public void Run () {
        try {
            mmethod.invoke (null, new object[] {Margs}),
        catch (Illegalaccessexception ex) { C3/>throw new RuntimeException (ex);
        } catch (InvocationTargetException ex) {
            throwable cause = Ex.getcause ();
            if (cause instanceof runtimeexception) {
                throw (runtimeexception) cause;
            } else if (cause instanceof Error) {
                throw (Error) cause;
            }
            throw new RuntimeException (ex);
        }
    

This executes the Mmethod method, which passes the assignment through the construction method Mmethod
New Zygoteinit.methodandargscaller (M, argv);

Method M;
    try {
        m = Cl.getmethod ("main", new class[] {string[].class});
    \ catch (Nosuchmethodexception ex) {
        throw new RuntimeException (
                "Missing static main on" + ClassName, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException (
                "Problem getting static main on" + ClassName, ex); 
  
   }

  

The Mthread here executes the main method, which is the main method of Activitythread

Activitythread

public static void Main (string[] args) {
    samplingprofilerintegration.start ();
    Closeguard.setenabled (false);
    Environment.initforcurrentuser ();
    Eventlogger.setreporter (New Eventloggingreporter ());
    Security.addprovider (New Androidkeystoreprovider ());
    Process.setargv0 ("<pre-initialized>");
    Mainthread do not use their own prepare ()
    looper.preparemainlooper ();
    Incredibly new self
    activitythread thread = new Activitythread ();
    Thread.attach (false);
    if (Smainthreadhandler = = null) {
        Smainthreadhandler = Thread.gethandler ();
    }
    Asynctask.init ();
    if (false) {
        looper.mylooper (). setmessagelogging (New
                Logprinter (Log.debug, "Activitythread"));
    Handler Looper cycle
    looper.loop ();
    throw new RuntimeException ("Main thread loop unexpectedly exited");
}

Next is the execution of the MessageQueue, followed by the execution of Dispatchinputevent ()

Inputeventreceiver

Called from native code.
private void dispatchinputevent (int seq, inputevent event) {
    mseqmap.put (event.getsequencenumber (), seq);
    Oninputevent (event);
}

This is the way out of the bottom, finally pleasing to the eye
This method is to handle the distribution input event

public void Oninputevent (InputEvent event) {
    Finishinputevent (event, false);
}

This method is invoked when there is an input event, which does not execute the Finishinputevent () method and executes the Viewrootimpl in the
The Oninputevent () of the Windowinputeventreceiver class;
Windowinputeventreceiver inherited the Inputeventreceiver.

Viewrootimpl$windowinputeventreceiver

Final class Windowinputeventreceiver extends Inputeventreceiver {public
    windowinputeventreceiver (inputchannel Inputchannel, Looper looper) {
        super (Inputchannel, Looper);
    }
    @Override public
    void Oninputevent (InputEvent event) {
        enqueueinputevent (event, this, 0, true);
    @Override public
    void Onbatchedinputeventpending () {
        scheduleconsumebatchedinput ();
    }
    @Override public
    void Dispose () {
        unscheduleconsumebatchedinput ();
        Super.dispose ();
    }

Then execute enqueueinpoutevent ()

Viewrootimpl

void Enqueueinputevent (InputEvent event,
        inputeventreceiver receiver, int flags, Boolean processimmediately) {
    queuedinputevent q = obtainqueuedinputevent (event, receiver, flags);
    Queuedinputevent last = Mpendinginputeventtail;
    if (last = = null) {
        mpendinginputeventhead = q;
        Mpendinginputeventtail = q;
    } else {
        last.mnext = q;
        Mpendinginputeventtail = q;
    }
    Mpendinginputeventcount + 1;
    Trace.tracecounter (Trace.trace_tag_input, Mpendinginputeventqueuelengthcountername,
            Mpendinginputeventcount);
    Whether if
    (processimmediately) {
        doprocessinputevents () is executed immediately;
    } else {
        scheduleprocessinputevents ();
    }
}

Then Doprocessinputevents ();

void Doprocessinputevents () {
    //Deliver all pending input events in the queue.
    while (Mpendinginputeventhead!= null) {
        queuedinputevent q = mpendinginputeventhead;
        Mpendinginputeventhead = Q.mnext;
        if (Mpendinginputeventhead = = null) {
            mpendinginputeventtail = null;
        }
        Q.mnext = null;
        Mpendinginputeventcount-= 1;
        Trace.tracecounter (Trace.trace_tag_input, Mpendinginputeventqueuelengthcountername,
                Mpendinginputeventcount);
        Delivery processing input Event
        deliverinputevent (q);
    }
    Complete processing of all input events clear Flag
    if (mprocessinputeventsscheduled) {
        mprocessinputeventsscheduled = false; 
        Mhandler.removemessages (msg_process_input_events);
    }

Then Deliverinputevent ();

private void Deliverinputevent (Queuedinputevent q) {
    trace.tracebegin (Trace.trace_tag_view, "Deliverinputevent" );
    try {
        if (minputeventconsistencyverifier!= null) {
            minputeventconsistencyverifier.oninputevent (q.mEvent, 0) ;
        }
        The stage base class for processing input events
        inputstage stage = Q.shouldskipime ()? mfirstpostimeinputstage:mfirstinputstage;
        if (stage!= null) {
            //input phase Delivery processing
            stage.deliver (q);
        } else {
            finishinputevent (q);
        }
    } finally {
        trace.traceend (Trace.trace_tag_view);
    }
}

Viewrootimpl$inputstage

Deliver the event to be processed public
final void deliver (Queuedinputevent q) {
        if (Q.mflags & Queuedinputevent.flag_ Finished)!= 0) {
            forward (q);
        } else if (Shoulddropinputevent (q)) {
            finish (q, False);
        } else {
            Apply (q, onprocess (q));
        }
    

then apply ();

Applies the event to the specified event
protected void apply (queuedinputevent q, int result) {
        if (result = = FORWARD) {
            FORWARD (q); 
  } else if (result = = finish_handled) {
            finish (q, True);
        } else if (result = = finish_not_handled) {
            finish (q), FALSE);
        else {
            throw new illegalargumentexception ("Invalid Result:" + result);
        }
    

Then forward (q);

    Throws the event down one stage
    protected void forward (Queuedinputevent q) {
        ondelivertonext (q);
    }

Then Ondelivertonext ();

    protected void Ondelivertonext (Queuedinputevent q) {
        if (mnext!= null) {
            //Next stage followed by
            Mnext.deliver (q); c21/>} else {
            finishinputevent (q);
        }
    }

Then deliver the processing deliver (q), execute the Apply () method, where apply () is a subclass of the method

Viewrootimpl$asyncinputstage

Asyncinputstage enables asynchronous processing of events as well as base classes for sequential processing stages

@Override
    protected void apply (queuedinputevent q, int result) {
        if (result = = DEFER) {
            DEFER (q);
        } else {
            super.apply (q, result);
        }
    

Then it executes the Apply method of the parent class, inputstage apply (), and executes the asyncinputstage forward ()

@Override protected void Forward (Queuedinputevent q) {//Clear delay flag q.mflags &= ~queuedinputevent.flag
        _deferred;
        If the queue is empty, then queuedinputevent curr = Mqueuehead;
            if (Curr = = null) {Super.forward (q);
        Return
        //Determine if the event is serialized before passing to the next stage final int deviceId = Q.mevent.getdeviceid ();
        Queuedinputevent prev = null;
        Boolean blocked = false;
                while (Curr!= null && curr!= q) {if (!blocked && deviceId = = Curr.mEvent.getDeviceId ()) {
            blocked = true;
            } prev = Curr;
        Curr = Curr.mnext; //If blocked will be placed in the queue for later processing, if the delay may not be placed in the queue if (blocked) {if (Curr = null) {Enqueue
            (q);
        } return;
            }//event does not prevent immediate handover processing if (Curr!= null) {Curr = Curr.mnext;
        Dequeue (q, prev); } super.forward (q); while (Curr!= null) {if (deviceId = = Curr.mEvent.getDeviceId ()) {if (Curr.mflags & Que
                uedinputevent.flag_deferred)!= 0) {break;
                } queuedinputevent next = Curr.mnext;
                Dequeue (Curr, prev);
                Super.forward (Curr);
            Curr = Next;
                else {prev = Curr;
            Curr = Curr.mnext;
 }
        }
    }

The forward () method of the parent class is then executed, followed by the Ondelivertonext (), Deliver () of the parent class, and the final execution of Viewpostimeinputstage.onprocess (), Viewpostimeinputstage also inherited Inputstage.

Viewrootimpl$viewpostimeinputstage

@Override
    protected int onprocess (queuedinputevent q) {
        if (q.mevent instanceof keyevent) {
            return Processkeyevent (q);
        } else {
            //If a new Non-key event is delivered, make sure window is now allowed to update
            handledispatchdoneanimating ();
            Final int source = Q.mevent.getsource ();
            if ((Source & Inputdevice.source_class_pointer)!= 0) {return
                processpointerevent (q);
            } else if ((source &am P Inputdevice.source_class_trackball)!= 0) {return
                processtrackballevent (q);
            } else {
                return Processgenericmotionevent (q);}}
    

Then Processpointerevent (q) starts processing the event distribution

private int processpointerevent (queuedinputevent q) {
        final motionevent event = (motionevent) q.mevent;
        The Mview here is Decorview, which is assigned in the Setview of Viewrootimpl.
        Understanding the source knows that the Makevisible method in the activity's series process in Windowmangerglobal will be new Viewrootimpl and will call Setview method
        if ( Mview.dispatchpointerevent (Event)) {return
            finish_handled;
        }
        return FORWARD;
    }

Then execute the view's Dispatchpointerevent ()

View

Public Final Boolean dispatchpointerevent (Motionevent event) {
    //whether to touch event
    if (Event.istouchevent ()) {
        Return Dispatchtouchevent (event);
    } else {return
        dispatchgenericmotionevent (event);
    }
}

followed by the execution of the Decorview dispatchtouchevent ()

Phonewindow$decorview

@Override Public
    Boolean dispatchtouchevent (motionevent ev) {
        //This performs the callback of the Dispatchtouchevent ()
        final Callback cb = Getcallback ();
        Return CB!= NULL &&!isdestroyed () && Mfeatureid < 0? Cb.dispatchtouchevent (EV)
                : super.dispatchtouchevent (EV);
    

The callback here is the window's callback interface, and activitiy implements the window's callback interface, which cb.dispatchtouchevent () The dispatchtouchevent of the activity is carried out ()

Activity

This is also the dispatchtoucheveent () public
boolean dispatchtouchevent (motionevent ev) {if () that we use in the activity.
    Ev.getaction () = = Motionevent.action_down) {
        onuserinteraction ();
    }
    if (GetWindow (). superdispatchtouchevent (EV)) {return
        true;
    }
    return ontouchevent (EV);
}

Then GetWindow () superdispatchtouchevent () was executed.
Window is an interface, and its implementation class is Phonewindow

Phonewindow

@Override Public
Boolean superdispatchtouchevent (Motionevent event) {
    //again handed to Decorview
    return Mdecor.superdispatchtouchevent (event);
}

Phonewindw$decorview

public boolean superdispatchtouchevent (Motionevent event) {return
        super.dispatchtouchevent (event);
    }

ViewGroup

Handling the distribution of the event public
Boolean dispatchtouchevent (Motionevent event) {
    //Check the Touch event
    ( Minputeventconsistencyverifier!= null) {
        minputeventconsistencyverifier.ontouchevent (event, 0);
    }
    if (onfiltertoucheventforsecurity (event)) {
        //noinspection simplifiableifstatement
        listenerinfo li = Mlistenerinfo;
        Ontouchlistener level is higher than ontouchevent ()
        if (Li!= null && li.montouchlistener!= null && (Mviewflags & Amp Enabled_mask = = ENABLED
                && li.mOnTouchListener.onTouch (this, event)) {return
            true;
        }
        if (Ontouchevent (event)) {return
            true;
        }
    }
    if (minputeventconsistencyverifier!= null) {
      minputeventconsistencyverifier.onunhandledevent (event, 0);
    } return
    false;

Then Dispatchtransformedtouchevent ()

Private Boolean dispatchtransformedtouchevent (Motionevent event, Boolean cancel, View child, int desiredpointeridb

    Its) {final boolean handled;
    To get the action, the important thing is the action, not the content final int oldaction = Event.getaction ();
        if (Cancel | | oldaction = = motionevent.action_cancel) {event.setaction (motionevent.action_cancel);
        If the subclass is empty, the dispatchhtouchevent if (child = = NULL) {handled = Super.dispatchtouchevent (event) of the parent class is executed;
        } else {handled = Child.dispatchtouchevent (event) that is not an empty execution subclass;
        } event.setaction (Oldaction);
    return handled;
    Final int oldpointeridbits = Event.getpointeridbits ();
    Final int newpointeridbits = oldpointeridbits & desiredpointeridbits;
    For some reason the event does not have pointer if (newpointeridbits = = 0) {return false;
    Final Motionevent transformedevent; if (newpointeridbits = = oldpointeridbits) {if (child = = NULL | | Child.hasidentitymatrix ()) {
            if (child = = NULL) {handled = Super.dispatchtouchevent (event);
                else {final float OffsetX = mscrollx-child.mleft;
                Final float OffsetY = mscrolly-child.mtop;

                Event.offsetlocation (OffsetX, OffsetY);

                handled = Child.dispatchtouchevent (event);
            Event.offsetlocation (-offsetx,-offsety);
        return handled;
    } transformedevent = Motionevent.obtain (event);
    else {transformedevent = Event.split (newpointeridbits);
    } if (child = = NULL) {handled = Super.dispatchtouchevent (transformedevent);
        else {final float OffsetX = mscrollx-child.mleft;
        Final float OffsetY = mscrolly-child.mtop;
        Transformedevent.offsetlocation (OffsetX, OffsetY);
        if (! Child.hasidentitymatrix ()) {Transformedevent.transform (Child.getinversematrix ()); } handled = CHIld.dispatchtouchevent (transformedevent);
    } transformedevent.recycle ();
return handled;
 }

The process ends here, until the event is processed.

To sum up,

1. From the bottom of the trigger to pass to Mainthread, Mainthread handed to viewrootimpl inputstage processing distribution input Events
2.->view.dispatchpointerevent
3.->phonewindow.decorview.dispatchtouchevent ()
4.->activity.dispatchtouchevent ()
5.->phonewindow.superdispatchtouchevent ()
6.->phonewindow.decorview.superdispatchtouchevent ()
7.->viewgroup.dispatchtouchevent ()

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.