Android源码分析之 - 从Button点击事件来分析Java接口回调
Android源码分析之 - 从Button点击事件来分析Java接口回调
1.1 最终效果
1.2 实例目录
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系统内部机制来控制发起的,而接口的实现是由用户自己控制的,因此可以在接口实现要执行的方法中写入响应接口回调的代码