从我所读到的,你可以用两种方式为按钮分配onClick处理程序。
使用android:onClick XML属性,你只是使用一个公共方法的名称与signaturevoid名称(View v)或通过使用setOnClickListener方法,你传递一个实现OnClickListener接口的对象。后者通常需要一个匿名类,我个人不喜欢(个人口味)或定义一个实现OnClickListener的内部类。
通过使用XML属性,你只需要定义一个方法而不是一个类
想知道同样的事情是否可以通过代码而不是在XML布局中完成。
不,通过代码是不可能的。当你定义Android:onClick="someMethod"属性时,Android只是实现了OnClickListener。
这两个代码段是相等的,只是以两种不同的方式实现。
代码实现
Button btn = (Button) findViewById(R.id.mybutton);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myFancyMethod(v);
}
});
// some more code
public void myFancyMethod(View v) {
// does something very interesting
}
上面是OnClickListener的代码实现。这是XML实现。
XML实现
<?xml version="1.0" encoding="utf-8"?>
<!-- layout elements -->
<Button android:id="@+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me!"
android:onClick="myFancyMethod" />
<!-- even more layout elements -->
在后台,Android只做Java代码,在点击事件时调用你的方法。
注意,使用上面的XML, Android将只在当前Activity中寻找onClick方法myFancyMethod()。如果你正在使用片段,记住这一点很重要,因为即使你使用片段添加上面的XML, Android也不会在用于添加XML的片段的.java文件中查找onClick方法。
我注意到另一件重要的事情。你提到你不喜欢匿名方法。你的意思是说你不喜欢匿名课程。
在Java 8中,您可以使用Method Reference来实现您想要的功能。
假设这是按钮的onClick事件处理程序。
private void onMyButtonClicked(View v) {
if (v.getId() == R.id.myButton) {
// Do something when myButton was clicked
}
}
然后,像这样在setOnClickListener()调用中传递onMyButtonClicked实例方法引用。
Button myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(this::onMyButtonClicked);
这将允许您避免自己显式地定义匿名类。然而,我必须强调,Java 8的Method Reference实际上只是一个语法糖。它实际上为您创建了一个匿名类的实例(就像lambda表达式所做的那样),因此当您要取消事件处理程序的注册时,会应用lambda表达式风格的事件处理程序。这篇文章解释得很好。
PS.对于那些好奇我如何在Android中真正使用Java 8语言功能的人,这是retrolambda库的礼貌。
小心,虽然android:onClick XML似乎是一个方便的方式来处理点击,setOnClickListener实现做一些额外的添加onClickListener。实际上,它把视图属性clickable设为true。
虽然这可能不是大多数Android实现的问题,根据手机构造函数,按钮总是默认为clickable = true,但在一些手机模型上的其他构造函数可能在非button视图上有默认clickable = false。
所以设置XML是不够的,你必须一直考虑在非按钮上添加android:clickable="true",如果你有一个默认为clickable= true的设备,你甚至忘记放置这个XML属性,你不会在运行时注意到这个问题,但会在市场上得到反馈,当它将在你的客户手中!
此外,我们永远无法确定proguard将如何混淆和重命名XML属性和类方法,所以不是100%安全,它们永远不会有任何错误。
因此,如果你不想有麻烦,也不想想它,最好使用setOnClickListener或ButterKnife这样的库,annotation @OnClick(R.id.button)