[英]Pros and cons of XML onClickListener vs programatic approach
I would like to find which approach is better for binding onClickListener
in Android. 我想找到哪种方法更适合在Android中绑定
onClickListener
。
There are several major ways to achieve this. 有几种主要方法可以实现此目的。 We can use
android:onClick
attribute in XML
, a programmatic approach: 我们可以使用
XML
(一种编程方法)中的android:onClick
属性:
findViewById(R.id.button1).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
//Add some logic
}
}
);
And various DataBinding libraries like ButterKnife
. 还有各种数据绑定库,例如
ButterKnife
。 For the sake of simplicity let's leave the data binding libraries aside and focus on the XML attribute VS programmatic approach. 为了简单起见,我们将数据绑定库放在一边,而将重点放在XML属性VS编程方法上。
In my opinion, the XML attribute is superior for the following reasons: 我认为,由于以下原因,XML属性是优越的:
findViewById
portion), but with the XML attribute, Android does it for us. findViewById
部分),但是使用XML属性,Android会为我们完成此操作。 onClick
, but with the XML attribute, we can add any name we want, which will dramatically help with the readability of the code. onClick
,但是使用XML属性,我们可以添加所需的任何名称,这将大大有助于代码的可读性。 onClick
attribute has been added by Google in the API level 4 release, which means that it is a bit more modern. onClick
属性,这意味着它更加现代。 And the new syntax is almost always better. Obviously, we cannot use the XML attribute with Fragments, but as far as the Activities go, it looks like a superior approach to me. 显然,我们不能将XML属性与Fragments一起使用,但是就Activity而言,对我来说,这似乎是一种更好的方法。
That said, in my experience, the programmatic approach seems to be preferred. 就是说,根据我的经验,程序化方法似乎是首选。 Am I missing something?
我想念什么吗?
I prefer much more the programmatic approach for two reasons: 由于两个原因,我更喜欢编程方法:
Centralized management of the click events : in this case you must use the same method to manage all clicks, instead of a custom method that you can change. 点击事件的集中管理 :在这种情况下,您必须使用相同的方法来管理所有点击,而不是可以更改的自定义方法。 Example:
例:
public class ActivityA extends Activity implements View.OnClickListener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
findViewById(R.id.first).setOnClickListener(this);
findViewById(R.id.second).setOnClickListener(this);
findViewById(R.id.third).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.first:
// Manage click.
break;
case R.id.second:
// Manage click.
break;
case R.id.third:
// Manage click.
break;
}
}
}
Performance : the programmatic approach is more performant than the XML one for two reasons. 性能 :出于两个原因,编程方法比XML方法更具性能。 The first one is that every time that you declare the
android:onClick
attribute in XML, a new DeclaredOnClickListener
will be instantiated. 第一个是每次您以XML声明
android:onClick
属性时,都会实例化一个新的DeclaredOnClickListener
。 It's more performant to have a shared click listener if you have more than one View
in the same tree. 如果同一棵树中有多个
View
,则拥有一个共享的Click侦听器会更有效。 The second one is that DeclaredOnClickListener
uses reflection internally to invoke your method. 第二个是
DeclaredOnClickListener
内部使用反射来调用您的方法。
Same pattern across different components : you can't use the XML approach in a Fragment
so you must change the way you declare click listener from Activity
to Fragment
. 跨不同组件的模式相同 :不能在
Fragment
使用XML方法,因此必须将声明Click监听器的方式从Activity
更改为Fragment
。 Instead, if you use the programmatic approach, you apply the same pattern both in Activity
and Fragment
. 相反,如果您使用编程方法,则可以在
Activity
和Fragment
应用相同的模式。
I'll share also my personal experience: in the past, at the first times, I used also the XML approach. 我还将分享我的个人经验:在过去的第一次,我也使用XML方法。 Now, I never use it for a project, because, also if you write more code in the programmatic approach, I think it's more ordered.
现在,我从不将其用于项目,因为,如果您以编程方式编写更多代码,我认为它的顺序也更合理。
Use DataBinding library so that you don't need to call findViewById(int)
for each view repeatedly. 使用DataBinding库 ,这样就不必为每个视图重复调用
findViewById(int)
。 A public final field will be generated for each View with an ID in the layout. 将为每个在布局中具有ID的视图生成一个公共最终字段。 The binding does a single pass on the View hierarchy, extracting the Views with IDs.
绑定对View层次结构进行一次传递,提取具有ID的View。 This mechanism can be faster than calling
findViewById(int)
for several Views. 这种机制可能比为多个视图调用
findViewById(int)
更快。
MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());
setup clickListener for necessary views as follows. 设置clickListener以获取必要的视图,如下所示。
binding.button1.setOnClickListener(this);
binding.button2.setOnClickListener(this);
Handle all button click events with in the onClick(View)
implementation so that you don't need to add individual anonymous listener for each button. 在
onClick(View)
实现中处理所有按钮单击事件,因此您无需为每个按钮添加单独的匿名侦听器。 Anonymous inner classes should be avoided where ever possible because anonymous classes will hold an implicit reference to the outer class. 应尽可能避免使用匿名内部类,因为匿名类将隐含对外部类的引用。
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
onClickButton1();
break;
case R.id.button2:
onClickButton2();
break;
}
}
So we can conclude that the programmatic approach with Data binding seems to be preferred. 因此,我们可以得出结论, 采用数据绑定的程序设计方法似乎是首选。
Xml approach vs programmatic approach: Xml方法与程序方法:
pros using xml approach 使用xml方法的专业人士
pros using programmatic approach 使用程序化方法的专业人士
conclusion : It totally depends on developer and requirements- 结论 :这完全取决于开发人员和要求-
if there are too many on click methods in one activity than one can choose programmatic approach as it will be very tedious to follow xml approach and write too many on click methods for every element. 如果一个活动中的单击方法太多,则不能选择编程方法,因为遵循xml方法并为每个元素编写过多的单击方法将非常繁琐。
Also, if the no. 另外,如果没有。 of onclick is not very much in an activity than its a commonsense to use xml approach as there will not be too many methods to write and it will increase readability of code.
onclick的活动与其说是使用xml方法的常识,不如说是一项活动,因为它不会编写太多的方法,并且会增加代码的可读性。
xml approach example : xml方法示例 :
main.xml : main.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="92dp"
android:onClick="clickFunc1"
android:text="Click me" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="92dp"
android:onClick="clickFunc2"
android:text="Click me" />
</RelativeLayout
MainActivity.java : MainActivity.java :
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void clickFunc1(View view){
Toast.makeText(MainActivity.this, "Button1 Clicked", Toast.LENGTH_SHORT).show();
}
public void clickFunc2(View view){
Toast.makeText(MainActivity.this, "Button2 Clicked", Toast.LENGTH_SHORT).show();
}
}
programmatic approach : 程序化方法 :
main.xml : main.xml :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="92dp"
android:text="Click me" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="92dp"
android:text="Click me" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="92dp"
android:text="Click me" />
</RelativeLayout>
MainActivity.java : MainActivity.java :
public class MainActivity extends Activity implements View.OnClickListener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
findViewById(R.id.button3).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
Toast.makeText(MainActivity.this, "Button1 Clicked", Toast.LENGTH_SHORT).show();
break;
case R.id.button2:
Toast.makeText(MainActivity.this, "Button2 Clicked", Toast.LENGTH_SHORT).show();
break;
case R.id.button3:
Toast.makeText(MainActivity.this, "Button3 Clicked", Toast.LENGTH_SHORT).show();
break;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.