我在非Java和非Android领域拥有丰富的经验,我正在学习Android。
我对不同领域有很多困惑,其中之一就是如何处理按钮点击。至少有4种方法(!!!),他们简要列出here
为了保持一致性,我将列出它们:
View.OnClickListener
类的成员,并将其分配给将在onClick
活动方法中处理onCreate
逻辑的实例。问题#1:
这些都是方法,还有其他选择吗? (我不需要任何其他的,只是好奇)
对我来说,最直观的方式是最新的方式:它需要输入最少量的代码并且是最可读的(至少对我而言)。
虽然,我没有看到这种方法被广泛使用。使用它有什么用处?
问题2:
每种方法的优缺点是什么?请分享您的经验或良好的链接。
欢迎任何反馈!
附:我已经尝试过谷歌并为这个主题找到了一些东西,但我发现的唯一的事情是描述“如何”这样做,而不是为什么它是好还是坏。
问题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步:创建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!
#1当布局上的按钮没有生成时(但显然是静态的),我经常使用最后一个。
如果您在实践中和业务应用程序中使用它,请在此处格外注意,因为当您使用像ProGuard这样的source obfuscater时,您需要在活动中标记这些方法,以免被混淆。
要使用这种方法存档某种编译时安全性,请查看Android Lint(example)。
#2所有方法的优缺点几乎相同,教训应该是:
使用最合适或最直观的方式。
如果必须将相同的OnClickListener
分配给多个按钮实例,请将其保存在类范围内(#1)。如果您需要一个简单的Button监听器,请进行匿名实现:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Take action.
}
});
我倾向于不在活动中实现OnClickListener
,这有时会让人感到有些困惑(特别是当你实现多个其他事件处理程序时,没有人知道this
在做什么)。
我更喜欢选项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更难。
最常用的方式是匿名声明
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布局中的多个按钮,也可以为一个按钮创建一个方法,但在这种情况下我更喜欢在活动类中声明处理程序。
选项1和2涉及使用内部类,这将使代码变得混乱。选项2有点乱,因为每个按钮都会有一个监听器。如果您的按钮数量很少,这没关系。对于选项4,我认为这将更难调试,因为你将不得不返回第四个xml和java代码。当我必须处理多个按钮点击时,我个人使用选项3。
我的样本,在Android studio 2.1中测试过
在xml布局中定义按钮
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Java脉动检测
Button clickButton = (Button) findViewById(R.id.btn1);
if (clickButton != null) {
clickButton.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
/***Do what you want with the click here***/
}
});
}
为了简化asp问题2,你可以使用这样的lambda方法来保存可变内存并避免在视图类中上下导航
//method 1
findViewById(R.id.buttonSend).setOnClickListener(v -> {
// handle click
});
但是如果您希望在方法中立即将click事件应用于您的按钮。
您可以使用@D的问题3。 Tran回答。但是不要忘记使用View.OnClickListener
实现您的视图类。
在其他方面正确使用问题#3
问题#1 - 这是处理视图点击的唯一方法。
问题2 - 选项#1 /选项#4 - 选项#1和选项#4之间没有太大区别。我看到的唯一区别是在一个案例中,活动是实现OnClickListener,而在另一个案例中,有一个匿名实现。
选项#2 - 在此方法中,将生成匿名类。这个方法有点麻烦,因为如果你有多个按钮,你需要多次这样做。对于匿名类,您必须小心处理内存泄漏。
选项#3 - 尽管如此,这是一种简单的方法。通常,程序员在编写之前不会尝试使用任何方法,因此这种方法并没有被广泛使用。您会看到大多数人使用选项#4。因为它在代码方面更干净。
还有各种库形式的选项可以使这个过程对使用其他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()}"
/>