在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和函数名称提供相同的名称。