源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

详细介绍Android中回调函数机制

  • 时间:2020-08-08 06:47 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:详细介绍Android中回调函数机制
提示:在阅读本文章之前,请确保您对Touch事件的分发机制有一定的了解 在Android的学习过程中经常会听到或者见到“回调”这个词,那么什么是回调呢?所谓的回调函数就是:在A类中定义了一个方法,这个方法中用到了一个接口和该接口中的抽象方法,但是抽象方法没有具体的实现,需要B类去实现,B类实现该方法后,它本身不会去调用该方法,而是传递给A类,供A类去调用,这种机制就称为回调。 下面我们拿具体的Button的点击事件进行模拟分析: 首先,在View类中我们能找到setOnClickListener(OnClickListener l)方法:
[u]复制代码[/u] 代码如下:
public void setOnClickListener(OnClickListener l) {      if (!isClickable()) {          setClickable(true);      }      getListenerInfo().mOnClickListener = l; }
可以看到,在该方法中将OnClickListener赋值给了mOnClickListener,那么我们继续向下找,会看到在performClick()方法中执行了我们实现的onClick()方法。
[u]复制代码[/u] 代码如下:
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; }
由此我们可以清楚的看不到,在父类中我们要用到onClick()方法,但是父类却没有去实现该方法,而是定义了一个方法setOnClickListener(OnClickListener l),如果子类想要自己能够响应点击事件,则它就必须重写父类的该方法,实现OnClickListener接口和它的onClick()方法。在子类实现该接口和方法后,将其通过参数传递给父类,在父类中执行onClick()方法。 那么,为什么会在父类中执行到该方法呢,这就要说到Android中的另一个重要的机制——触摸事件的传递机制。 我们知道,只要我们的手指触摸到手机屏幕,就一定会执行dispatchTouchEvent(MotionEvent event)方法,接下来我们就看一下dispatchTouchEvent方法中都有哪些内容:
[u]复制代码[/u] 代码如下:
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; }
这里我们不细讲Touch事件的分发机制,因为网上有哥们已经讲的很清楚了。请参看篇首提供的链接。 我们看一下第17行,由于我们没有实现OnTouchListener接口,而onTouch()方法的默认返回值为false,所以第一个if语句中的代码不会被执行到,进入第二个if语句中,执行了onTouchEvent()方法。那么我们再来看一下该方法:
[u]复制代码[/u] 代码如下:
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;     }
代码太长,我们只看重点,在ACTION_UP这个case当中,我们找到了关键的代码(第109行):performClick()。 至此,我们已经基本搞清楚了回调机制的整个过程。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部