Explanation of callback function mechanism in Android

Source: Internet
Author: User

Tip: Before reading this article, make sure that you have a certain understanding of the Touch event distribution mechanism. If you do not understand it, see: Touch event distribution mechanism.

In the course of Android learning, I often hear or see the word "Callback". What is callback? The so-called callback function defines a method in the parent class. This method uses an interface class and an abstract method in the class, but the abstract method has no specific implementation, it must be implemented by a subclass. After the subclass implements this method, it will not call this method, but will pass it to the parent class for the parent class to call. This mechanism is called callback.

Next, we will simulate and analyze the click events of a specific Button:

First, we can find the setOnClickListener (OnClickListener l) method in the View class:

public void setOnClickListener(OnClickListener l) {     if (!isClickable()) {         setClickable(true);     }     getListenerInfo().mOnClickListener = l;}


As you can see, OnClickListener is assigned to mOnClickListener in this method, so we continue to look down and we will see that the onClick () method we implemented is executed in the javasmclick () method.

public boolean performClick() {     sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);     ListenerInfo li = mListenerInfo;     if (li != null && li.mOnClickListener != null) {         playSoundEffect(SoundEffectConstants.CLICK);         li.mOnClickListener.onClick(this);         return true;     }     return false;}

From this we can clearly see that the onClick () method is used in the parent class, but the parent class does not implement this method, but defines a method setOnClickListener (OnClickListener l ), if the subclass wants to respond to the click event, it must override the method of the parent class to implement the OnClickListener interface and its onClick () method. After the subclass implements this interface and method, it passes the parameter to the parent class and executes the onClick () method in the parent class.

So, why is this method executed in the parent class? This is about another important mechanism in Android-the transfer mechanism of touch events.

We know that as long as our fingers touch the mobile phone screen, we will certainly execute the dispatchTouchEvent (MotionEvent event) method. Next we will take a look at what is included in the dispatchTouchEvent method:

public boolean dispatchTouchEvent(MotionEvent event) {        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onTouchEvent(event, 0);        }         if (onFilterTouchEventForSecurity(event)) {            //noinspection SimplifiableIfStatement            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnTouchListener != null                     && (mViewFlags & ENABLED_MASK) == ENABLED                    && li.mOnTouchListener.onTouch(this, event)) {                return true;            }             if (onTouchEvent(event)) {                return true;            }        }         if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);        }        return false;}


Here we will not elaborate on the Touch event distribution mechanism, because some online friends have already made it very clear. See the link at the beginning of the article.

Let's take a look at row 17th. Because we didn't implement the OnTouchListener interface, and the default return value of the onTouch () method is false, the code in the first if statement will not be executed, in the second if statement, the onTouchEvent () method is executed. Then let's take a look at this method:

public boolean onTouchEvent(MotionEvent event) {        final int viewFlags = mViewFlags;         if ((viewFlags & ENABLED_MASK) == DISABLED) {            if (event.getAction() == MotionEvent.ACTION_UP                      && (mPrivateFlags & PFLAG_PRESSED) != 0) {                setPressed(false);            }            // A disabled view that is clickable still consumes the touch            // events, it just doesn't respond to them.            return (((viewFlags & CLICKABLE) == CLICKABLE ||                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));        }         if (mTouchDelegate != null) {            if (mTouchDelegate.onTouchEvent(event)) {                return true;            }        }         if (((viewFlags & CLICKABLE) == CLICKABLE ||                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {            switch (event.getAction()) {                case MotionEvent.ACTION_UP:                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {                        // take focus if we don't have it already and we should in                        // touch mode.                        boolean focusTaken = false;                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {                            focusTaken = requestFocus();                        }                         if (prepressed) {                            // The button is being released before we actually                            // showed it as pressed.  Make it show the pressed                            // state now (before scheduling the click) to ensure                            // the user sees it.                            setPressed(true);                       }                         if (!mHasPerformedLongPress) {                            // This is a tap, so remove the longpress check                            removeLongPressCallback();                             // Only perform take click actions if we were in the pressed state                            if (!focusTaken) {                                // Use a Runnable and post this rather than calling                                // performClick directly. This lets other visual state                                // of the view update before click actions start.                                if (mPerformClick == null) {                                    mPerformClick = new PerformClick();                                }                                if (!post(mPerformClick)) {                                    performClick();                                }                            }                        }                         if (mUnsetPressedState == null) {                            mUnsetPressedState = new UnsetPressedState();                        }                         if (prepressed) {                            postDelayed(mUnsetPressedState,                                    ViewConfiguration.getPressedStateDuration());                        } else if (!post(mUnsetPressedState)) {                            // If the post failed, unpress right now                            mUnsetPressedState.run();                        }                        removeTapCallback();                    }                    break;                 case MotionEvent.ACTION_DOWN:                    mHasPerformedLongPress = false;                     if (performButtonActionOnTouchDown(event)) {                        break;                    }                     // Walk up the hierarchy to determine if we're inside a scrolling container.                    boolean isInScrollingContainer = isInScrollingContainer();                     // For views inside a scrolling container, delay the pressed feedback for                    // a short period in case this is a scroll.                    if (isInScrollingContainer) {                        mPrivateFlags |= PFLAG_PREPRESSED;                        if (mPendingCheckForTap == null) {                            mPendingCheckForTap = new CheckForTap();                        }                        postDelayed(mPendingCheckForTap,                                    ViewConfiguration.getTapTimeout());                    } else {                        // Not inside a scrolling container, so show the feedback right away                        setPressed(true);                        checkForLongClick(0);                    }                    break;                 case MotionEvent.ACTION_CANCEL:                    setPressed(false);                    removeTapCallback();                    removeLongPressCallback();                    break;                 case MotionEvent.ACTION_MOVE:                    final int x = (int) event.getX();                    final int y = (int) event.getY();                     // Be lenient about moving outside of buttons                    if (!pointInView(x, y, mTouchSlop)) {                        // Outside button                        removeTapCallback();                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {                            // Remove any future long press/tap checks                            removeLongPressCallback();                             setPressed(false);                        }                    }                    break;            }            return true;        }         return false;    }

The code is too long. Let's focus on it. In the ACTION_UP case, we found the key code (line 1): Semi mclick ().

So far, we have basically figured out the entire process of the callback mechanism.

Original articles can be freely transmitted, but please indicate the source for reprinting.

Related Article

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.