Android event distribution mechanism - system default mechanism

Keywords: Android Fragment Java jvm

1. Why do you want to understand the Android event mechanism?

Background: when I was working on the Android project, I encountered a nested relationship like activity - > fragment - > Scrollview - > Button. When everything was ready, the system crashed when I clicked the Button after the program was started. Tencent Button reported the following error when it caught it.

java.lang.IllegalArgumentException

Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter e1

Needless to see, there is a problem with the parameters passed. To solve this problem, you must understand the event distribution mechanism of Android.

2. How to solve.

Let me take a look at an Android event distribution mechanism

 

As can be seen from the above figure, when clicking a View on Activity, Android shows its complete system default event distribution mechanism Activity - > ViewGroup - > View.

Activity(DispatchTouchEvent)->(VIewGroup)DispatchTouchEvents->(VIewGroup)onInterceptTouchEvent->(view)dispatchTouchEvent->(View)OnTouchEvent

Case 1:

Create a new DispatchEvent project;

Create a new mylinarlayout

class MyLinearLayout(context:Context): LinearLayout(context)
{
    override  fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        when(ev?.action)
        {
            MotionEvent.ACTION_DOWN->{
                Log.d("GroupView_dispatchEvent","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{Log.d("GroupView_dispatchEvent","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{Log.d("GroupView_dispatchEvent","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{
                (Log.d("GroupView_dispatchEvent","ACTION_CANCEL"))
            }
        }

        return super.dispatchTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        when(ev?.action)
        {
            MotionEvent.ACTION_DOWN->{Log.d("GroupView_onIntercept","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{Log.d("GroupView_onIntercept","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{Log.d("GroupView_onIntercept","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{Log.d("GroupView_onIntercept","ACTION_CANCEL")}
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when(event?.action)
        {
            MotionEvent.ACTION_DOWN->{Log.d("GroupView_onTouchEvent","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{Log.d("GroupView_onTouchEvent","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{Log.d("GroupView_onTouchEvent","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{Log.d("GroupView_onTouchEvent","ACTION_CANCEL")}
        }
        return super.onTouchEvent(event)
    }
}

 

 

2. Create a new MyButton

class MyButton(context:Context): Button(context)
{
    override  fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        when(ev?.action)
        {
            MotionEvent.ACTION_DOWN->{    Log.d("View_dispatchEvent","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{    Log.d("View_dispatchEvent","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{    Log.d("View_dispatchEvent","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{
                Log.d("View_dispatchEvent","ACTION_CANCEL")
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when(event?.action)
        {
            MotionEvent.ACTION_DOWN->{Log.d("View_onTouchEvent","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{Log.d("View_onTouchEvent","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{Log.d("View_onTouchEvent","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{Log.d("View_onTouchEvent","ACTION_CANCEL")}
        }
        Log.d("View_onTouchEvent","I'm the last consumer ${super.onTouchEvent(event)}")
        return super.onTouchEvent(event)
    }
}

 

3. Write the following code in MainActivity

 

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        var myLinearLayout = MyLinearLayout(this);
        var myButton = MyButton(this);
        myButton.setText("MyButton")

        var viewGroups:ViewGroup.LayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);

        var viewPar:ViewGroup.LayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        myLinearLayout.orientation = LinearLayout.VERTICAL;
        myLinearLayout.addView(myButton,viewPar);

        setContentView(myLinearLayout,viewGroups);
    }

    override  fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        when(ev?.action)
        {
            MotionEvent.ACTION_DOWN->{  Log.d("Activity_dispatchEvent","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{  Log.d("Activity_dispatchEvent","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{  Log.d("Activity_dispatchEvent","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{
                Log.d("Activity_dispatchEvent","ACTION_CANCEL")
            }
        }

        return super.dispatchTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when(event?.action)
        {
            MotionEvent.ACTION_DOWN->{Log.d("Activity_onTouchEvent","ACTION_DOWN")}
            MotionEvent.ACTION_MOVE->{Log.d("Activity_onTouchEvent","ACTION_MOVE")}
            MotionEvent.ACTION_UP->{Log.d("Activity_onTouchEvent","ACTION_UP")}
            MotionEvent.ACTION_CANCEL->{Log.d("Activity_onTouchEvent","ACTION_CANCEL")}
        }
        return super.onTouchEvent(event)
    }

}

Click button to observe the printing information

09-29 00:20:11.109 8276-8276/com.example.krcm110.myapplication D/Activity_dispatchEvent: ACTION_DOWN
09-29 00:20:11.116 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_DOWN
09-29 00:20:11.117 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_DOWN
09-29 00:20:11.118 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_DOWN
09-29 00:20:11.118 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_DOWN
09-29 00:20:11.151 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: I'm the last consumer true
09-29 00:20:11.154 8276-8276/com.example.krcm110.myapplication D/Activity_dispatchEvent: ACTION_UP
09-29 00:20:11.154 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_UP
09-29 00:20:11.155 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_UP
09-29 00:20:11.155 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_UP
09-29 00:20:11.155 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_UP
09-29 00:20:11.156 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: I'm the last consumer true

The above is a complete event distribution as shown in Figure 1

4. If we don't release it immediately after clicking and move the mouse, release it again

09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/Activity_dispatchEvent: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_DOWN
09-29 00:30:45.193 8276-8276/com.example.krcm110.myapplication D / view'ontouchevent: I am the last consumer true09-29 00:30:45.328 8276-8276/com.example.krcm110.myapplication D / activity'dispatchevent: action'move
09-29 00:30:45.328 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_MOVE
09-29 00:30:45.329 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_MOVE
09-29 00:30:45.329 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_MOVE
09-29 00:30:45.329 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_MOVE
I am the last consumer true09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D / activity "dispatchEvent: action" up
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_UP
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_UP
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_UP
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_UP
09-29 00:30:45.573 8276-8276/com.example.krcm110.myapplication D / view "ontoucheevent: I am the last consumer true

Summary: the above is a system default Android event mechanism. I believe there are some B numbers in your heart.

 

 

 

 

 

 

 

Posted by Francois on Mon, 23 Dec 2019 11:17:02 -0800