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>的集合)。