本文将解析Android View的onClick事件的回调机制,通过这个设计,可以明白接口和对象组合是非常重要的。记得我们在写Button的onClick事件是往往会这样来写:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
首先定义个类,姑且就叫它BaseView,跟Android SDK里面的View对应
package com.example.callbacktest;
public class BaseView {
interface OnClickMyListener {
public void onClick(BaseView view);
};
}
该类里面有个内部接口,叫OnClickMyListener在,这与Android SDK中OnClickListener对应。接下来写两个BaseView的子类ViewA、ViewB
package com.example.callbacktest;
public class ViewA extends BaseView{
private OnClickMyListener mLinstener ;
public void click(){
mLinstener.onClick(this);
}
public void setOnClickMyListener(OnClickMyListener linstener){
mLinstener = linstener ;
}
}
package com.example.callbacktest;
public class ViewB extends BaseView{
private OnClickMyListener mLinstener ;
public void click(){
mLinstener.onClick(this);
}
public void setOnClickMyListener(OnClickMyListener linstener){
mLinstener = linstener ;
}
}
package com.example.callbacktest;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewA viewA = new ViewA();
ViewB viewB = new ViewB();
viewA.setOnClickMyListener(new BaseView.OnClickMyListener() {
@Override
public void onClick(BaseView view) {
Log.e("MainActivity","viewA-->onClick");
}
});
viewB.setOnClickMyListener(new BaseView.OnClickMyListener() {
@Override
public void onClick(BaseView view) {
Log.e("MainActivity","viewB-->onClick");
}
});
Log.e("MainActivity","now click A:");
viewA.click();
Log.e("MainActivity","now click B:");
viewB.click();
}
}
现在来说一下这个流程,首先在View中定义一个接口,接口中的方法就是回调方法,即onClick(BaseView view),这个方法的参数是BaseView类型,也就是说凡是继承自BaseView的子类并且需要用这个接口来实例化回调监听器的类都可以响应这个回调方法。就像这里的ViewA、ViewB一样,这相当于Android SDK里面的Button或ImageView等等,他们都是继承自View,并且需要OnClickListener去实例化onClick事件监听器。
这里的ViewA、ViewB有自己的click方法,这个方法按理由来说不应该在主程序中主动调用,这个方法应该是屏幕捕捉到一个点击屏幕的动作之后转换成坐标,如果这个坐标对应的是该View,那么才调用它的click方法,也就是说是屏幕获取点击事件,来触发View的click事件,进而调用了事件监听器的onClick方法,而onClick方法是在外部实现的,所以就会调用onClick里面的打印信息。这就是整个调用的流程。