在非Java和非Android领域拥有丰富的经验,我正在学习Android。
我对不同领域有很多困惑,其中之一就是如何处理按钮点击。至少有4种方法(!!!),它们被简要列出here
为了保持一致性,我将列出它们:
在活动中拥有View.OnClickListener
类的成员,并将其分配给将在onClick
活动方法中处理onCreate
逻辑的实例。
在'onCreate'活动方法中创建'onClickListener'并使用setOnClickListener
在活动本身中实现'onClickListener'并将'this'指定为按钮的侦听器。对于活动按钮很少的情况,应分析按钮ID以执行适当按钮的“onClick”处理程序
对实现'onClick'逻辑的活动设置公共方法,并将其分配给活动xml声明中的按钮
问题#1:
这些是所有方法,还有其他选择吗? (我不需要任何其他的,只是好奇的)
对我来说,最直观的方式是最新的方式:它需要输入的代码量最少且最易读(至少对我而言)。
虽然,我没有看到这种方法被广泛使用。使用它有什么用处?
问题#2:
这些方法的优点/缺点是什么?请分享您的经验或良好的链接。
欢迎任何反馈!
P.S。我试过谷歌并找到了一些关于这个话题的东西,但我发现的唯一的事情是描述“如何”这样做,而不是为什么它好或坏。
答案 0 :(得分:133)
问题1: 不幸的是,你说的最直观的是在Android中使用最少的。据我所知,您应该分离UI(XML)和计算功能(Java类文件)。它还使调试更容易。通过这种方式阅读并考虑Android imo实际上要容易得多。
问题2: 我相信主要使用的两个是#2和#3。我将使用Button clickButton作为示例。
采用匿名类的形式。
Button clickButton = (Button) findViewById(R.id.clickButton);
clickButton.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
***Do what you want with the click here***
}
});
这是我最喜欢的,因为它的onClick方法就在使用findViewById设置按钮变量的旁边。处理此clickButton Button View的所有内容都位于此处,看起来非常整洁。
我的同事评论的一个骗局是,想象你有很多需要onclick听众的观点。你可以看到你的onCreate的篇幅会很长。这就是他喜欢使用的原因:
说你有,5 clickButtons:
确保您的Activity / Fragment实现OnClickListener
// in OnCreate
Button mClickButton1 = (Button)findViewById(R.id.clickButton1);
mClickButton1.setOnClickListener(this);
Button mClickButton2 = (Button)findViewById(R.id.clickButton2);
mClickButton2.setOnClickListener(this);
Button mClickButton3 = (Button)findViewById(R.id.clickButton3);
mClickButton3.setOnClickListener(this);
Button mClickButton4 = (Button)findViewById(R.id.clickButton4);
mClickButton4.setOnClickListener(this);
Button mClickButton5 = (Button)findViewById(R.id.clickButton5);
mClickButton5.setOnClickListener(this);
// somewhere else in your code
public void onClick(View v) {
switch (v.getId()) {
case R.id.clickButton1: {
// do something for button 1 click
break;
}
case R.id.clickButton2: {
// do something for button 2 click
break;
}
//.... etc
}
}
正如我的同事所解释的那样,他的眼睛更加整洁,因为所有onClick计算都在一个地方处理,而不是拥挤onCreate方法。但我看到的缺点是:
如果您想了解更多信息,请与我们联系。我没有完全回答你的问题,因为这是一个很长的问题。如果我找到一些网站,我会扩展我的答案,现在我只是给一些经验。
答案 1 :(得分:10)
#1 当布局上的按钮没有生成时(但显然是静态的),我经常使用最后一个。
如果您在实践中和业务应用程序中使用它,请在此处格外注意,因为当您使用像ProGuard这样的source obfuscater时,您需要在活动中标记这些方法,以免被混淆。< / p>
要使用此方法归档某种编译时安全性,请查看Android Lint(example)。
#2 所有方法的优缺点几乎相同,应该是:
使用最合适或最直观的方式。
如果必须为多个按钮实例分配相同的OnClickListener
,请将其保存在类范围内(#1)。如果您需要一个简单的Button监听器,请进行匿名实现:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Take action.
}
});
我倾向于不在活动中实现OnClickListener
,这有时会让人感到有些困惑(特别是当你实现多个其他事件处理程序而没有人知道this
正在做什么时)
答案 2 :(得分:8)
我更喜欢选项4,但它对我来说很直观,因为我在Grails,Groovy和JavaFX中做了太多工作。视图和控制器之间的“魔术”连接是共同的。为方法命名很重要:
在视图中,将onClick方法添加到按钮或其他小部件:
android:clickable="true"
android:onClick="onButtonClickCancel"
然后在课堂上处理方法:
public void onButtonClickCancel(View view) {
Toast.makeText(this, "Cancel pressed", Toast.LENGTH_LONG).show();
}
再次,明确地命名方法,无论如何应该做的事情,维护成为第二性质。
一个很大的优点是您现在可以为该方法编写单元测试。选项1可以做到这一点,但2和3更难。
答案 3 :(得分:4)
最常用的方式是匿名声明
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// handle click
}
});
此外,您可以创建View.OnClickListener对象并稍后将其设置为按钮,但您仍需要覆盖onClick方法,例如
View.OnClickListener listener = new View.OnClickListener(){
@Override
public void onClick(View v) {
// handle click
}
}
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(listener);
当您的活动实现OnClickListener接口时,您必须在活动级别上覆盖onClick(View v)方法。然后你可以把这个活动作为按钮的监听器,因为它已经实现了接口并覆盖了onClick()方法
public class MyActivity extends Activity implements View.OnClickListener{
@Override
public void onClick(View v) {
// handle click
}
@Override
public void onCreate(Bundle b) {
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(this);
}
}
(imho)当多个按钮具有相同的处理程序时使用的第4种方法,您可以在活动类中声明一个方法并将此方法分配给xml布局中的多个按钮,也可以为一个按钮创建一个方法,但是这个案子我更喜欢 在活动类中声明处理程序。
答案 4 :(得分:1)
选项1和2涉及使用内部类,这将使代码变得混乱。 选项2有点乱,因为每个按钮都会有一个监听器。如果您的按钮数量很少,这没关系。 对于选项4,我认为这将更难调试,因为你将不得不返回第四个xml和java代码。 当我必须处理多个按钮点击时,我个人使用选项3。
答案 5 :(得分:1)
我的示例,在Android studio 2.1中测试
在xml布局中定义按钮
<security-constraint>
<web-resource-collection>
<web-resource-name>InternalUserRole</web-resource-name>
<url-pattern>/jsp/internal/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>InternalUser</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/jsp/login/login.jsp</form-login-page>
<form-error-page>/jsp/login/login.jsp?Retry=True</form-error-page>
</form-login-config>
</login-config>
Java脉动检测
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
答案 6 :(得分:1)
为了简化问题,问题2说明,您可以使用这样的lambda方法来保存可变内存并避免在视图类中上下导航
//method 1
findViewById(R.id.buttonSend).setOnClickListener(v -> {
// handle click
});
但是如果您希望在方法中立即将点击事件应用于您的按钮。
您可以使用@D的问题3。 Tran回答。但是不要忘记使用View.OnClickListener
实现您的视图类。
在其他方面正确使用问题#3
答案 7 :(得分:0)
问题#1 - 这是处理视图点击的唯一方法。
问题#2 -
选项#1 /选项#4 - 选项#1和选项#4之间没有太大区别。我看到的唯一区别是一个案例活动是实现OnClickListener,而在另一个案例中,有一个匿名实现。
选项#2 - 在此方法中,将生成匿名类。这个方法有点麻烦,因为如果你有多个按钮,你需要多次这样做。对于匿名类,您必须小心处理内存泄漏。
选项#3 - 尽管如此,这是一种简单的方法。通常,程序员在编写之前不会尝试使用任何方法,因此这种方法并没有被广泛使用。您会看到大多数人使用选项#4。因为它在代码方面更干净。
答案 8 :(得分:0)
第1步:创建XML文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btnClickEvent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me" />
</LinearLayout>
第2步:创建MainActivity:
package com.scancode.acutesoft.telephonymanagerapp;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity implements View.OnClickListener {
Button btnClickEvent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnClickEvent = (Button) findViewById(R.id.btnClickEvent);
btnClickEvent.setOnClickListener(MainActivity.this);
}
@Override
public void onClick(View v) {
//Your Logic
}
}
<强> HappyCoding!强>
答案 9 :(得分:0)
还有各种库形式的选项可以使这个过程对使用其他MVVM框架的人非常熟悉。
https://developer.android.com/topic/libraries/data-binding/
显示官方库的示例,允许您绑定如下按钮:
<Button
android:text="Start second activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{() -> presenter.showList()}"
/>