**在布局文件中设置Button的点击事件,代码中方法要传入View的原因分析**

             **在布局文件中设置Button的点击事件,代码中方法要传入View的原因分析**

本人大四实习生小菜鸟一枚,近期工作中想到了个在大学期间遇到的不解问题。就是以前老师介绍添加四种点击事件是在布局文件中引用方法,然后在代码中构造一个同名的方法即可。需要注意的是方法参数必须传入View,当时一直奇怪为什么要加入一个那样的东西。
近期工作遇到又遇到这个问题花了点时间研究了下原因,特此来分享下,不足或者错误之处请前辈多多指教。
由于这篇文章是我在CSDN上的第一篇文章,可能写的有点不好,敬请谅解。
开门见山的说,我是在Button控件上添加该方法的,于是我去看了下Button的源码发现了个惊人现象,Button里的源代码居然如此简洁。我之前还以为onClick 方法是在Button这个类中的。结果发现源码如下:
@RemoteView
public class Button extends TextView {
public Button(Context context) {
this(context, null);
}

public Button(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.buttonStyle);
}

public Button(Context context, AttributeSet attrs, int defStyleAttr) {
    this(context, attrs, defStyleAttr, 0);
}

public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

@Override
public CharSequence getAccessibilityClassName() {
    return Button.class.getName();
}

}
就是这么简洁,我于是想找到button的onClick方法定义在哪里,我进入了button的父类TextView去看了看,发现TextView的方法很多,于是我下意识地心想:原来onClick方法在这里,怪不得TextView有点击事件,正当我准备去详细看看这个方法时发现在这个类里找了很久也没有找到这个方法。难道这个方法不在TextView里?我又怀着激动地心情点开了TextView的父类View去瞧了瞧。在TextView里终于有了重要发现。
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
在TextView里定义了一个CallBack接口当View被点击时会被反射调用。并且onClick抽象方法终于找到了,方法参数中确确实实传入了View。于是只要找到实现这个接口的实类这个问题就可以得到解决了,我便迫不及待地去寻找,接着找到了下面代码:
private static class DeclaredOnClickListener implements OnClickListener {
private final View mHostView;
private final String mMethodName;

    private Method mMethod;

    public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
        mHostView = hostView;
        mMethodName = methodName;
    }

    @Override
    public void onClick(@NonNull View v) {
        if (mMethod == null) {
            mMethod = resolveMethod(mHostView.getContext(), mMethodName);
        }

        try {
            mMethod.invoke(mHostView.getContext(), v);
        } catch (IllegalAccessException e) {
            throw new IllegalStateException(
                    "Could not execute non-public method for android:onClick", e);
        } catch (InvocationTargetException e) {
            throw new IllegalStateException(
                    "Could not execute method for android:onClick", e);
        }
    }

源码中一个静态类DeclaredOnClickListener 实现了OnClickListener 接口,并且重写了onClick方法。
mMethod.invoke(mHostView.getContext(), v);这行代码用传入的方法名反射实现了方法调用,并且传入的参数是一个上下文,还有一个是View!
所以我们在布局文件中设置的点击事件必须在代码方法中传入一个View才能使上述代码运行成功。
以上就是我对在布局文件中设置点击事件的一种理解,有理解错误之处还望大侠批评指正小弟。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值