平时,我们开发,Button控件一般就是如下使用:
先在布局文件中定义Button控件:
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TestButton" />
再在java文件中使用此Button控件:
//定义Button
private Button button = null;
//定义接口OnClickListener
private View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG,"View.OnClickListener--onClick");
}
};
//获取button对象
button = (Button)findViewById(R.id.button);
//设置button点击事件监听接口
button.setOnClickListener(onClickListener);
执行程序,当button点击时,执行接口OnClickListener中的onClick方法,打印Log:
View.OnClickListener--onClick
我们查看源码—View.java
OnClickListener 接口定义:
因此,响应点击Button后的操作,各个控件,各个场景都不一样,是一个可变的动作,所以android定义了一个接口OnClickListener来应对这个可变的因素:
public interface OnClickListener {
/** * Called when a view has been clicked. * * @param v The view that was clicked. */
void onClick(View v);
}
定义内部的OnClickListener变量mOnClickListener:
/** * Listener used to dispatch click events. * This field should be made private, so it is hidden from the SDK. * {@hide} */
public OnClickListener mOnClickListener;
setOnClickListener方法:
public void setOnClickListener(OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
//给mOnClickListener变量赋值
getListenerInfo().mOnClickListener = l;
}
执行click的方法performClick:
/** * Call this view's OnClickListener, if it is defined. Performs all normal * actions associated with clicking: reporting accessibility event, playing * a sound, etc. * * @return True there was an assigned OnClickListener that was called, false * otherwise is returned. */
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
//播放点击声音
playSoundEffect(SoundEffectConstants.CLICK);
//执行点击的回调方法onClick
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
return result;
}
执行click的方法callOnClick:
/** * Directly call any attached OnClickListener. Unlike {@link #performClick()}, * this only calls the listener, and does not do any associated clicking * actions like reporting an accessibility event. * * @return True there was an assigned OnClickListener that was called, false * otherwise is returned. */
public boolean callOnClick() {
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
//执行点击的回调方法onClick
li.mOnClickListener.onClick(this);
return true;
}
return false;
}
点击button是在什么时候点击监听回调接口:
boolean performAccessibilityActionInternal(int action, Bundle arguments) {
switch (action) {
//ACTION_CLICK 点击Button
case AccessibilityNodeInfo.ACTION_CLICK: {
if (isClickable()) {
//执行点击button监听接口
performClick();
return true;
}
} break;
......
......
public boolean onTouchEvent(MotionEvent event) {
......
//可以点击
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
switch (event.getAction()) {
//button ACTION_UP
case MotionEvent.ACTION_UP:
......
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
//执行点击button监听接口
performClick();
}
......
我们为了让大家真正看明白android为什么如此设计Button是这样响应点击事件,我们再定义一个MyButtonOnClickListener类:
//类MyButtonOnClickListener实现接口View.OnClickListener,实现方法onClick:
public class MyButtonOnClickListener implements View.OnClickListener {
public static final String TAG = "MyButtonOnClickListener";
@Override
public void onClick(View v) {
Log.i(TAG,"MyButtonOnClickListener--onClick");
}
}
然后,我们再实现点击Button代码:
//定义Button
private Button button = null;
//定义MyButtonOnClickListener
private MyButtonOnClickListener myButtonOnClickListener = new MyButtonOnClickListener();
//获取button对象
button = (Button)findViewById(R.id.button);
//设置button点击事件监听接口myButtonOnClickListener
button.setOnClickListener(myButtonOnClickListener);
现在,我们列出uml类图:
大家看类图,应该是不是觉得有一点眼熟呢?是不是和策略模式的类图相似呢?
对,这就是一个最简单的策略模式。
android开发笔记之监听者模式—http://blog.csdn.net/hfreeman2008/article/details/37568615
这是我以前写的一篇文章,非常好的应用了接口。
定义接口:
接口IListener:
public interface IListener {
public void run();
}
定义一个Body类:
public class Body {
//定义一个IListener类型的变量listener
private IListener listener = null;
//设置Listener
public void setListener(IListener listener){
this.listener = listener;
}
//执行方法
public void dosomething(){
System.out.println("Body--dosomething()--before");
if(listener != null){
//这才是接口方法的调用的地方,也是用于后面的地方实现的地方
listener.run();
}
System.out.println("Body--dosomething()--after");
}
}
我们再定义一个接口实现类ListenerTest01:
public class ListenerTest01 implements IListener {
//ListenerTest01实现接口IListener中run方法
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("ListenerTest01---run()");
}
}
我们在Client中使用:
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//定义一个对象listener,大家常用这一种方式,实现接口IListener中run方法
IListener listener = new IListener() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("listener---run()");
}
};
//定义一个对象listenerTest01
IListener listenerTest01 = new ListenerTest01();
//我们没有设置Listener
System.out.println("---------------------");
Body body = new Body();
body.dosomething();
//我们设置Listener为listener
System.out.println("---------------------");
body.setListener(listener);
body.dosomething();
//我们设置Listener为listenerTest01
System.out.println("---------------------");
body.setListener(listenerTest01);
body.dosomething();
}
}
输出结果:
--------------------- Body--dosomething()--before Body--dosomething()--after ---------------------
Body--dosomething()--before
listener---run()
Body--dosomething()--after ---------------------
Body--dosomething()--before
ListenerTest01---run()
Body--dosomething()--after
从输出结果,我们可以看到:
如果不设置Listener,就直接执行对象的dosomething方法,而不执行listener.run()方法。
如果我们设置Listener为listener,则执行listener—run()方法。
如果我们设置Listener为ListenerTest01,则执行ListenerTest01—run()方法。
接口是将一个行为操作的实现放到后面具体类,具体位置来实现,并且此行为操作还可以改变。