欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android源码分析之 - 从Button点击事件来分析Java接口回调

程序员文章站 2022-05-14 10:06:49
...

Android源码分析之 - 从Button点击事件来分析Java接口回调

1.1 最终效果

Android源码分析之 - 从Button点击事件来分析Java接口回调

1.2 实例目录

Android源码分析之 - 从Button点击事件来分析Java接口回调

1.3 源码分析

1.3.1 点击事件执行方法一

  • 点击事件
public class MainActivity extends AppCompatActivity {

    private Button button;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        clickEvent();
    }

    private void initView() {
        button = findViewById(R.id.button);
        textView = findViewById(R.id.textview);
    }

    private void clickEvent() {
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.setText("我是点击后的结果");
            }
        });
    }

}
  • 点击button执行点击事件
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 响应点击事件
    }
});
  • 源码分析

先看button.setOnClickListener()的源码,跳转到View内部执行View的setOnClickListener()方法,这是因为Button继承自TextView,TextView有继承自View,因此Button可以执行View中的public方法:

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

看getListenerInfo()的源码:

ListenerInfo getListenerInfo() {
    if (mListenerInfo != null) {
        return mListenerInfo;
    }
    mListenerInfo = new ListenerInfo();
    return mListenerInfo;
}

它的作用是创建ListenerInfo实例,而ListenerInfo又是View的内部类,而mOnClickListener又是内部类ListenerInfo的一个成员变量,那么mOnClickListener是什么类型呢?

public interface OnClickListener {
    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    void onClick(View v);
}

可以看到OnClickListener是View内部定义的一个接口,这个接口规定执行onClick()方法

看源码getListenerInfo().mOnClickListener = l;,它将用户自己创建的View.OnClickListener的接口实例赋值给getListenerInfo().mOnClickListener即给View的内部类ListenerInfo中的变量OnClickListener赋值,因此在内部类ListenerInfo中执行mOnClickListener.onClick()方法就会回调到用户自定义的View.OnClickListener接口实例中的onClick()方法中,响应点击事件

1.3.2 点击事件执行方法二

  • 点击事件
public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button button;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        button.setOnClickListener(this);
    }

    private void initView() {
        button = findViewById(R.id.button);
        textView = findViewById(R.id.textview);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:
                textView.setText("我是点击之后的结果");
                break;
            default:
                break;
        }
    }
}

可以看到MainActivity实现了View.OnClickListener接口,因此MainActivity需要实现View.OnClickListener接口规定的方法onClick(),为了执行onClick()这个方法,需要将MainActivity的实例赋值给button.setOnClickListener(),先看button.setOnClickListener()的源码:

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

与1.3.1一样,用户将View.OnClickListener接口实例赋值给了View的setOnClickListener方法,这是因为MainActivity实现了View.OnClickListener接口,因此MainActivity的实例就是View.OnClickListener接口实例,下面就与1.3.1一样了,当在View的内部类ListenerInfo中执行mOnClickListener.onClick()方法时,就会回调到MainActivity中的onClick()方法中,去响应点击事件

1.4 接口回调的实质

接口回调时通过将接口的实现赋值给接口实行的,当执行接口操作时就会跳转到接口实现中执行

接口回调的实质就是将接口中方法的执行与实现进行分离

Button点击事件接口中方法在View的内部类ListenerInfo中执行,而接口中方法的实现是在MainActivity中进行,点击事件中接口的执行是由android系统内部机制来控制发起的,而接口的实现是由用户自己控制的,因此可以在接口实现要执行的方法中写入响应接口回调的代码