XML onClickListener与编程方法的优缺点

时间:2017-06-10 22:58:17

标签: java android xml

我想找到哪种方法更适合在Android中绑定onClickListener

有几种主要方法可以实现这一目标。我们可以在android:onClick中使用XML属性,这是一种程序化方法:

   findViewById(R.id.button1).setOnClickListener(
       new View.OnClickListener() {
          @Override
          public void onClick(View v) {
             //Add some logic
          }
       }
   );

各种DataBinding库,如ButterKnife。为简单起见,我们将数据绑定库放在一边,并专注于XML属性VS编程方法。

在我看来,XML属性优越,原因如下:

  1. 使用编程方法,我们总是必须为元素指定ID,但是使用XML属性可以省略它。
  2. 使用程序化方法类,我们必须主动搜索视图内部的元素(findViewById部分),但是使用XML属性,Android会为我们做。
  3. 我们可以看到,编程方法类需要至少五行代码,但使用XML属性,三行代码就足够了。
  4. 使用编程方法,我们必须将方法命名为onClick,但是使用XML属性,我们可以添加任何我们想要的名称,这将极大地帮助提高代码的可读性。
  5. Google在API级别4发布中添加了XML onClick属性,这意味着它更加现代化。新语法几乎总是更好。
  6. 显然,我们不能将XML属性与Fragments一起使用,但就活动而言,它看起来对我来说是一种更好的方法。

    那就是说,根据我的经验,程序化方法似乎更受欢迎。我错过了什么吗?

3 个答案:

答案 0 :(得分:3)

我更喜欢程序化方法,原因有两个:

点击事件的集中管理:在这种情况下,您必须使用相同的方法来管理所有点击,而不是您可以更改的自定义方法。例如:

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;
        }
    }
}

性能:由于两个原因,程序化方法比XML方法更高效。第一个是每次在XML中声明android:onClick属性时,都会实例化一个新的DeclaredOnClickListener。如果在同一个树中有多个View,则拥有共享的单击侦听器会更高效。第二个是DeclaredOnClickListener在内部使用反射来调用你的方法。

不同组件的相同模式:您无法在Fragment中使用XML方法,因此您必须更改从Activity向{{{l}}声明点击侦听器的方式1}}。相反,如果您使用程序化方法,则在FragmentActivity中应用相同的模式。

我也会分享我的个人经历:在过去,我第一次使用XML方法。现在,我从来没有将它用于项目,因为,如果你在编程方法中编写更多代码,我认为它更有序。

答案 1 :(得分:0)

使用DataBinding library,这样您就不需要为每个视图重复调用findViewById(int)。将为每个视图生成一个公共最终字段,并在布局中显示ID。绑定在View层次结构上执行单次传递,使用ID提取视图。 此机制可能比为多个视图调用findViewById(int)更快。

MainActivityBinding binding = MainActivityBinding.inflate(getLayoutInflater());

为必要的视图设置clickListener,如下所示。

binding.button1.setOnClickListener(this);
binding.button2.setOnClickListener(this);

onClick(View)实现中处理所有按钮单击事件,这样您就不需要为每个按钮添加单独的匿名侦听器。 应尽可能避免使用匿名内部类,因为匿名类将包含对外部类的隐式引用。

 @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
               onClickButton1();
                break;

            case R.id.button2:
               onClickButton2();
                break;


        }
    }

因此,我们可以得出结论,Data binding程序化方法似乎更受欢迎。

答案 2 :(得分:0)

Xml方法与程序化方法:

使用xml方法 专业人员

  • 在每个元素上都可以定义用户定义的方法
  • 用户定义的方法将具有完全限定名称
  • 使用完全限定名称声明方法可提高可读性
使用程序化方法

专业人员

  • 每个" onclick"您不必定义方法的每个元素的事件
  • 在编程方法中,这可以通过覆盖View.OnClickListener
  • 来声明一个onclick方法来实现。

<强>结论: 它完全取决于开发人员和要求 -

如果一个活动中的点击方法太多而不能选择程序化方法,因为遵循xml方法并为每个元素编写过多的点击方法将非常繁琐。

另外,如果没有。 onclick的活动并不是一个活动,而是使用xml方法的常识,因为没有太多的方法可以编写,它会增加代码的可读性。

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

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();
    }


}

程序化方法

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

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;
        }
    }
}