Android的Listener监听事件分析

Android中的回调一直是我难以理解的一部分,总是很容易绕进去,但是细细想一下其实这些方法或者称之为函数都是在一个线程乃至一个进程中执行,肯定会存在先后的顺序,下面就先分析一下Listener,以后再分析一下Callback的回调。

 下面的demo是我自定义的一个listener事件,其实他们的写法千篇一律,只要自己写一遍理解了以后就很容易了

public class CustomView {

    private Listener mListener;

    public void setListener(Listener listener) {
        this.mListener = listener;
    }

    public void operate(String string) {
        if (mListener != null) {
            mListener.onChange(string);
        }
    }

    interface Listener {   // 只需要在接口中添加想要实现的方法就行
        default void onChange(String string){
            System.out.println("default");
        }
    }
}

 在Activity中调用listener

public class MainActivity implements CustomView.Listener {
 	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 跟咱们平时用到的view监听事件保持一致
        CustomView view = new CustomView();
        view.setListener(MainActivity.this);
        view.onChange("true");// 这里我们需要自己调用一下方法
    }   
    
    @Override
    public void onChange(String string) {
        System.out.println("onChange: " + string);
    }
}

最终控制台会打印出onChange:true

 

再举一个源码中的实例加深大家的理解:在Android开发中我们经常用到的就是在View中的onClickListener,下面看一下它的源码(SDK29)

// 因为加上英文注释显得很乱,所以去掉,大家有兴趣可以直接点进去源码看一下
public OnClickListener mOnClickListener;

public interface OnClickListener {
    void onClick(View v);
}

public void setOnClickListener(@Nullable OnClickListener l) {// 不是很懂为什么变量名要叫l
    if (!isClickable()) {
        setClickable(true);
    }
    getListenerInfo().mOnClickListener = l;// 将OnClickListener赋值给了mOnClickListener
}

// 有很多地方调用了该方法,具体可以点击看一下
public boolean performClick() {
    notifyAutofillManagerOnClick();

    final boolean result;
    final ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnClickListener != null) {
        playSoundEffect(SoundEffectConstants.CLICK);
        // 这里执行onClick事件,具体的业务就是我们业务中在onClick方法中写的逻辑
        li.mOnClickListener.onClick(this);
        result = true;
    } else {
        result = false;
    }

    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

    notifyEnterOrExitForAutoFillIfNeeded(true);

    return result;
}
// 这里又牵涉到了触摸事件的分发机制,调用顺序为onTouch—>onTouchEvent—>onClick。上面performClick()方法的执行就是在下面的onTouchEvent()中调用的
 public boolean onTouchEvent(MotionEvent event) {
     ......
         
    if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
        // 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)) {
                performClickInternal();// 调用之处
            }
        }
    }
     
     ......
}

private boolean performClickInternal() {
    // Must notify autofill manager before performing the click actions to avoid scenarios where
    // the app has a click listener that changes the state of views the autofill service might
    // be interested on.
    notifyAutofillManagerOnClick();

    return performClick();
}

参考自 https://www.jianshu.com/p/3f86b7949f20

 

之前面试有被问到addListener和setListener的区别

显而易见,setListener只能设置一个监听,之后调用一个方法将会把之前的设置的监听覆盖,addListener可以设置多个监听,不会被覆盖(就是维护了一个List<Listener>的集合)。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值