在android中实现View.OnClickListener的最佳方法

假设我们有一个有很多关于哪个OnClickListener被注册的视图的Activity。

实现这个最常见的方法是让Activity-Subclass实现OnClickListener,如下所示:

 public class ActivityMain extends Activity implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } } 

我喜欢实现它的方式是在Activity-Subclass中创build一个私有类,并让该内部类实现OnClickListener:

 public class ActivityMain extends Activity implements View.OnClickListener { private class ClickListener implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } } } 

这样的代码似乎更有组织,易于维护。

而且,在谈到“Is-a”,“Has-a”关系时,后者似乎是一个很好的做法,因为现在Activity-Subclass与ClickListener有一个“Has-a”关系。 而在前一种方法中,我们会说我们的Activity-Subclass是“一个”ClickListener,这是不完全正确的。

请注意,我不关心后者会造成的内存开销。

另外,在XML中添加onClick标签是完全没有问题的。

那么,实现ClickListener的最好方法是什么?

请不要build议像RoboGuice或ButterKnife等任何图书馆

更新:

我想分享我最后通过的方法。

我直接在Activity / Fragment中实现监听器。

就OOPdevise而言。 “HAS-A”方法不提供任何实际的好处,甚至占用更多的记忆。 考虑到嵌套类的数量(和内存开销),我们将为每个我们实现的类似的监听器创build,这种方法应该避免。

首先,Android没有定义关于注册点击监听器的最佳做法。 这完全取决于你的用例。

实现View.OnClickListener接口到Activity是要走的路。 由于Android强烈推荐一遍又一遍的接口实现,无论它是一个Activity还是Fragment。

现在就像你所描述的:

 public class ActivityMain extends Activity implements View.OnClickListener { private class ClickListener implements View.OnClickListener { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } } } 

这是你的方法。 现在这是你的实现方式,如果你不关心内存开销,这没有什么错。 但是,如果您只需在主类中实现这一View.OnClickListener那么创build内部类和实现View.OnClickListener的好处是什么呢?这也可以使您的代码更加清晰和简单。

所以这只是一个讨论,而不是实现View.OnClickListener的最佳解决scheme,因为如果你把每个人的实际意义放在一起,你将会find一个简单和高效的解决scheme。

所以我更喜欢传统的方式。 它使事情简单而高效。 检查下面的代码:

 @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } 

PS:你的方法肯定会增加代码行数:P;)

首先让我们在这里弄清楚基础知识

通过实现一个接口,你的class级不会变成那样..就像你说的:

“我们的活动 – 子类”是一个“ClickListener,这是不完全正确的。”

如果您的课程延伸,您的课程只能有“是 – 一个”关系,在这种情况下是一个Activity 。 实现一个接口意味着它可以performance得像接口已经设置了合同。

一个例子:

彼得延伸人类意味着彼得是一个人类..

彼得也可以实现程序员,音乐家,丈夫等等彼得可以performance得如上。

至于最佳做法,你可以做一个完全独立的类来实现OnClickListener像这样:

 class MyListener implements View.OnClickListener{ @Override public void onClick(View view) { // do whatever you want here based on the view being passed } } 

在你的主Activity你可以实例化MyListener并调用onClick()并传入你的视图:

 MyListener listener = new MyListener(); Button b = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.button); listener.onClick(button); } 

我使用button.setOnClickListener(this); 我的Activity implements View.OnClickListener ,然后在一个单独的方法获得Button的ID。 看下面的例子:

 public class MyActivity extends ActionBarActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.YOUR_LAYOUT); ... Button myFirstButton = (Button) findViewById(R.id.YOUR_FIRST_BUTTON); myFirstButton.setOnClickListener(this); Button mySecondButton = (Button) findViewById(R.id.YOUR_SECOND_BUTTON); mySecondButton.setOnClickListener(this); ... } ... @Override public void onClick(View v) { Button b = (Button) v; switch(b.getId()) { case R.id.YOUR_FIRST_BUTTON: // Do something break; case R.id.YOUR_SECOND_BUTTON: // Do something break; ... } } ... } 

在这里,你可以创build一个btnClickListner对象,然后在你想要执行button的onCLieck动作的时候,你会调用这个btnCLickLisner对象。

让我们假设,在我的活动中,我有一个5到10个button,每个button单独的onclick listner是不好的主意。 所以为了过来这个,我们可以用下面的样子..

注册你的button

 Button button1 = (Button)findViewById(R.id.button1); Button button2 = (Button)findViewById(R.id.button2); Button button3 = (Button)findViewById(R.id.button3); Button button4 = (Button)findViewById(R.id.button4); Button button5 = (Button)findViewById(R.id.button5); 

在这里我点击后设置onclick listner到我的button

 button1.setOnClickListener(btnClickListner); button2.setOnClickListener(btnClickListner); button3.setOnClickListener(btnClickListner); button4.setOnClickListener(btnClickListner); button5.setOnClickListener(btnClickListner); 

这里是btnClick Listner的实现

 View.OnClickListener btnClickListner = new OnClickListener() { @Override public void onClick( View v ) { // TODO Auto-generated method stub if( button1.getId() == v.getId() ) { //Do Button1 click operations here } else if( button2.getId() == v.getId() ) { // Do Button2 click operations here } else if( button3.getId() == v.getId() ) { // Do Button3 click operations here } else if( button4.getId() == v.getId() ) { // Do Button4 click operations here } else if( button5.getId() == v.getId() ) { // Do Button5 click operations here } } } 

我发现使用Butterknife使干净的代码。 而且由于它使用代码生成(而不是reflection),所以性能开销很小。

 public class ActivityMain extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); } @OnClick(R.id.button_foo) void onFoodClicked() { // Do some foo } @OnClick(R.id.button_bar) void onBarClicked() { // do some bar } } 

你的ClickListener是一个内部的非静态类,这个“has-a”的耦合与你的类Activity实现View.OnClickListener没有什么不同。 这是因为你的内部ClickListener需要一个ActivityMain的实例,并且不能被重用。 我会争辩说,你是在工程,并没有真正获得任何东西。

编辑:要回答你的问题,我喜欢有每个部件的匿名View.OnClickListener 。 我认为这创造了逻辑的最佳分离。 我也有像setupHelloWorldTextView(TextView helloWorldTextView); 在那里我把我的所有逻辑相关的小部件。

第一种方法比另一种更好,因为这就是为什么View.OnClickListener是一个Interface而不是一个abstract class 。 除了后面可能在各种情况下泄漏,因为你正在使用一个非静态的内部类。

对于这个特定的情况,我会说保持一个OnClickListener的实例是最适合你的方法。 你将有一个“有一个”的关系,并且不需要创build多个实例,因为你正在使用onClick(View view)callback中的视图ID处理行为。

 public class ActivityMain extends Activity implements View.OnClickListener { private View.OnClickListener mClickListener = new View.OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { //handle multiple view click events } } }; } 

只是你使用像不实现子类或不处理一个点击事件就这样做。

 android.view.View.OnClickListener method_name = new android.view.View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // put your code . } }; 

并处理点击事件button亚任何types的点击事件

 button_name.setOnClickListener(method_name); 

其工作非常简单,谢谢

这真的取决于你想达到什么。 如果你有与线程,依赖等的复杂function,我个人喜欢将它从Activity完全解耦成一个单独的类XyzAction ,这是很重的东西,知道某些XyzAction ,并返回结果,如果需要的话。 我的OnTouch者基本上是实现OnClick / OnTouch /等的对象。 Listener并将自己绑定到需要的操作上。 例如,可以有一个LoginInvoker实现一个Button和一个ImageView OnClickListener ,还有一个通用的ActionListener ,当一个MenuItem被点击时被调用。 Invoker已经更新了向用户显示进度的方法以及绑定操作的结果。 行动职位更新到其Invoker ,可以被垃圾收集,如果他们都死了,因为它没有连接到用户界面。

对于较不复杂的动作,我直接将它们耦合到Android组件(即Activity / Feagment / View ),并将它们称为Actions ,它们直接实现了UIcallback的巨大差异。

在这两种情况下,我都将这些操作声明为成员,所以我可以快速浏览一下Android组件支持的具体操作。

如果有一些像“如果按下button显示吐司”这样的小事,我会使用匿名内部类来进行UIcallback,因为在可维护性方面你通常不关心它们。

对此的一个小小的评论,也许是一些话题。

如果我们不只是实现OnClickListener,而且还有其他一些Listener / Callback实现的话。 在我的意见,它会变得混乱,而不是使用匿名类/ lambda在类中实现所有这些。 很难记得这个方法属于哪个接口。

所以,如果我们必须多次实现一个接口(在这种情况下,OnClickListener),那么我可以很好地解决在类库上实现并使用开关/大小写的问题。

但是,如果我们必须实现多个接口,那么使用匿名类/ lambda可能是一个很好的解决scheme

您可以在XML文件中使用Button android:onClick="btn"属性,然后在java文件中,不需要查找buttonID。 你只需要做一个如下的函数:

 public void btn(View v){ //======Code that will occur on button click write here====== } 

请记住,您必须为onClick和函数名称提供相同的名称。