2013-02-08 135 views
67

在非Java和非Android领域有丰富的经验,我正在学习Android。Android:如何处理按钮点击

我对不同领域有很多困惑,其中之一是如何处理按钮点击。有这样做(!),他们简要列出here

一致性目的的至少4路,我会一一列举:

  1. 已经在活动View.OnClickListener类的成员,将其分配给将处理onCreate活动方法中的onClick逻辑的实例。在“的onCreate”活动方法

  2. 创建“onClickListener”和活动使用setOnClickListener

  3. 实施“onClickListener”本身它分配给该按钮并指定“本”为按钮的监听器。对于活动只有少量按钮的情况,应分析按钮ID以执行适当按钮的“onClick”处理程序

  4. 对实现'onClick'逻辑的活动具有公共方法并将其分配给活动中的按钮XML声明

问题1:

那些是所有方法中,还有没有其他的选择吗? (我不需要任何其他的,只是好奇)

对我来说,最直观的方法是最新的:它需要输入的代码量最少,并且是最具可读性的(至少对我而言) 。

虽然,我没有看到这种方法广泛使用。使用它有什么好处?

问题2:

有什么利弊/每个这些方法的利弊?请分享您的经验或一个很好的链接。

欢迎任何反馈!

P.S.我试图找到谷歌并为这个话题找到一些东西,但我发现的唯一事情是描述“如何”这样做,而不是为什么它是好的或坏的。

回答

108

问题1: 不幸的是,你说的最直观的是Android中最少使用的。据我所知,你应该分开你的UI(XML)和计算功能(Java Class Files)。它也使得调试更容易。实际上,阅读这种方式比较容易,并考虑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方法就在button变量设置在findViewById的旁边。看起来非常整洁,所有处理这个clickButton按钮视图的东西都在这里。

我的同事评论的一个骗局是想象你有很多需要onclick监听器的观点。你可以看到你的onCreate会变得很长。这样,为什么他喜欢用:

说你有,5个clickButtons:

确保您的活动/片段实现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. 看待自己,
  2. 和可能位于由OnClick方法中使用的onCreate任何其他对象将不得不做成一个字段。

让我知道如果您想了解更多信息。我没有完全回答你的问题,因为这是一个相当长的问题。如果我找到一些网站,我会扩大我的答案,现在我只是给一些经验。

+1

对于选项2,你会希望把它:clickButton.setOnClickListener(新View.OnClickListener(){@覆盖公共无效的onClick(视图v) {// TODO你想做什么}});以帮助解决OnClickListener – ColossalChris 2015-03-25 13:54:10

+0

选项3可能是使用MVP模式最简单和最容易扩展的选项。 – Raffaeu 2016-01-26 12:05:43

+0

选项2仍然可以生成'onCreate()',这不是很长。点击监听器分配和匿名类可以分解为一个单独的辅助方法,该方法从'onCreate()'调用。 – 2016-02-29 07:28:12

0

问题#1 - 这些是处理查看点击的唯一方法。

问题#2 -
选项#1 /选项#4 - 选项#1和选项#4没有太大区别。我看到的唯一区别是在一种情况下,活动正在实现OnClickListener,而在另一种情况下,会有一个匿名实现。

选项#2 - 在此方法中,将生成一个匿名类。这种方法有点笨拙,因为如果您有多个按钮,您需要多次执行此操作。对于匿名类,你必须小心处理内存泄漏。

选项#3 - 虽然这是一个简单的方法。通常,程序员在编写它们之前不要使用任何方法,因此这种方法没有被广泛使用。你会发现大多数人使用选项#4。因为它在代码方面更干净。

+0

嗨拉夫,感谢您的回答。但是,请您澄清一下您的意思:对于匿名类,您必须小心处理内存泄漏。内存泄漏如何来到这里? – Budda 2013-02-09 01:26:20

+0

你一定要知道:如果你创建你的应用程序不能将创建一个类的几个实例,但几类,包括它们的实例的生命周期过程中可能会多次调用方法内部的匿名类。您可以通过使用常规的内部类并将实例化侦听器作为实例字段来避免这种情况。尝试通过构造函数参数让侦听器状态感知来减少不同的侦听器类。常规的内部类为您提供自定义构造函数和其他方法的好处。 – Risadinha 2013-10-15 09:26:35

9

#1当布局上没有生成按钮(但显然是静态的)时,我经常使用最后一个按钮。

如果您在实践中和业务应用程序中使用它,请特别注意这一点,因为当您像ProGuard一样使用source obfuscater时,您需要在活动中标记这些方法以免被混淆。

要使用此方法归档某种编译时安全性,请查看Android Lintexample)。


#2利弊所有方法几乎相同和教训应该是:

使用什么都最合适的还是感觉最直观的给你。

如果您必须将相同的OnClickListener分配给多个按钮实例,请将其保存在类范围(#1)中。如果你需要一个简单的监听器按钮,使得一个匿名的实现:

button.setOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View view) { 
     // Take action. 
    } 
}); 

我倾向于不执行活动中的OnClickListener,这会有点混乱,不时(尤其是当你实现多个其他事件没有人知道什么this都在做)。

+0

我下面一样,但仍然没有得到任何输出功能,我的代码和查询是在这里:http://stackoverflow.com/questions/25107427/can-we-make-2-different-functions-in-same-jni -in-Android的NDK-使用-C/25187447 noredirect = 1#comment39221983_25187447 – Rocket 2014-08-07 19:42:57

1

选项1和2涉及使用内部类,将使代码种类杂乱。 选项2有点乱,因为每个按钮都会有一个监听器。如果你有少量的按钮,这没关系。 对于选项4,我认为这将更难以调试,因为您将不得不返回第四个xml和java代码。 当我必须处理多个按钮点击时,我个人使用选项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)方法。然后,你可以assing将此活动作为侦听器按钮,因为它已经实现了接口,并覆盖的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布局中的多个按钮,也可以为一个按钮创建一个方法,但在这种情况下,我倾向于使用 来在活动类中声明处理程序。

5

我更喜欢选项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更难。

+0

我要胡扯一点,并提出第五种选择(不,不是主演布鲁斯·威利斯:)),选项2的变体:使用演示类模型 - 视图 - 演示框架来处理点击。它使自动化测试更容易。查看此链接以获取更好的信息:https://codelabs.developers.google.com/codelabs/android-testing/index.html – 2017-06-29 13:50:58

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

1

我的样品,在Android Studio中测试2.1

在XML布局定义按钮

<Button 
    android:id="@+id/btn1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" /> 

Java的脉动检测

​​