android开发笔记之从Button点击说起

这里写图片描述

#Button使用
平时,我们开发,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

#android是怎么样设计此功能的

我们查看源码—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();
                    }
......

#再修改Button使用方法:

我们为了让大家真正看明白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开发中的样例

android开发笔记之监听者模式—http://blog.youkuaiyun.com/hfreeman2008/article/details/37568615

这是我以前写的一篇文章,非常好的应用了接口。

#接口在java开发中的样例

定义接口:

接口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()方法。

接口是将一个行为操作的实现放到后面具体类,具体位置来实现,并且此行为操作还可以改变。

常见的邮箱登录Demo

定义一个Email类,login时监听是登录成功还是失败,从而调用对应的接口:

public class Email {

    private String name = "test";
    private String passord = "test";

    private OnLoginListener onLoginListener;

    public boolean login(String name,String passord){

        if(this.name.equals(name) && this.passord.equals(passord)){
            if(onLoginListener != null){
                onLoginListener.onLoginSucess();
            }
            return true;
        }else{
            if(onLoginListener != null){
                onLoginListener.onLoginFail();
            }
            return false;
        }
    }

    public OnLoginListener getOnLoginListener() {
        return onLoginListener;
    }

    public void setOnLoginListener(OnLoginListener onLoginListener) {
        this.onLoginListener = onLoginListener;
    }

    public interface OnLoginListener {
        void onLoginSucess();
        void onLoginFail();
    }
}

具体的实现:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private String TAG = "InterfaceDemo";

    private Button button;
    private Email email;

    private boolean flag = false;

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

    private void init() {

        email = new Email();
        email.setOnLoginListener(new Email.OnLoginListener() {
            @Override
            public void onLoginSucess() {
                Log.i(TAG,"onLoginSucess");
            }

            @Override
            public void onLoginFail() {
                Log.i(TAG,"onLoginFail");
            }
        });

        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG,"onclick");
                if(flag){
                    email.login("test01","test01");
                    flag = false;
                }else{
                    email.login("test","test");
                    flag = true;
                }
            }
        });

    }
}

点击Button,模拟登录操作:

18871 18871 I InterfaceDemo: onclick
18871 18871 I InterfaceDemo: onLoginSucess
18871 18871 I InterfaceDemo: onclick
18871 18871 I InterfaceDemo: onLoginFail
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hfreeman2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值