Android onClickListener实现最佳实践

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android onClickListener实现最佳实践相关的知识,希望对你有一定的参考价值。

有四种方法可以将onClickListener添加到可单击的视图(例如按钮):

  1. 在布局文件中设置onClick属性,该属性指向活动中的方法,
  2. 创建一个匿名内部类,
  3. 将onClickListener分配给私有成员变量。
  4. 让Activity上下文实现onClickListener接口。

所以我的问题是,你如何选择其中一种实现技术呢?根据某些条件是否有最佳实践,还是仅仅是程序员偏好的问题?

答案

这里我们使用所谓的回调模式。

public class Button {
    private Callback callback;

    public Button(Callback callback) {
        this.callback = callback;
    }

    public void update() {
        // Check if clicked..
        callback.onClick(this);
    }

    public interface Callback {
        public void onClick(Button Button);
    }
}


Button b = new Button(new Callback() {
    @Override
    public void onClick(Button b) {
        System.out.println("Clicked");
    }
});

在我们的例子中,onClick处理程序实现了View.OnClickListener接口。

关键点:

  • 与活动/片段的一致性;
  • 访问活动/片段的成员;
  • 可读性;
  • @Michael Krause展示了关于memory leaks的另一个好点;

1)XML文件中的属性只能用于活动,因为@Karakuri提到它使用慢的反射。

2)匿名内部类具有访问封闭类成员的特殊规则(检查[1][2])。在某些情况下可能发生内存泄漏(例如使用AsyncTask,Handlers进行线程处理)。

3)在这里,您可以完全访问封闭类的成员。

4)是3d的变化。

可读性取决于您的处理程序大小,小逻辑可以内联,但对于较大的代码块,请考虑3d和4th。

另一答案

我从不使用onClick属性,因为它将布局绑定到特定的Activity(它必须通过反射找到方法)。它不适用于碎片。

选项2和3几乎相同。如果要将私有成员用作多个视图的OnClickListener,则选项3可能更有利。

选项4接近选项3.一个关键的区别是它改变了类声明,所以如果保持类声明不受接口实现(或者你需要保持某种二进制兼容性)的重要性,你可以不想使用这个选项。

我的建议是避免选项1,并选择最适合您的代码风格。您也不需要在代码中的每个位置使用相同的方法。

另一答案

使用OnClickListener有四种方法。

First way

在方法调用站点中定义OnClickListener

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button button = findViewById(R.id.myButton);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // do something
            }
        });
    }
}  

避免这种情况的第一个原因是因为它混淆了onCreate方法。当您想要观察来自多个视图的点击事件时,这一点变得更加明显。 避免这种情况的下一个原因是,如果几个按钮应该相同,它不会促进代码重用。

Second way

第二种方式与第一种方法几乎相同,只是在类中分配了实现到字段。

public class MainActivity extends AppCompatActivity {

    private View.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // do something
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button button = findViewById(R.id.myButton);
        button.setOnClickListener(clickListener);
    }
}  

这种方式与第一种方式非常相似,唯一的好处是该方法可以重复用于多个按钮。

Third way

这种方式是声明一个内部类来实现OnClickListener。如果将多次使用,最好将实例定义为字段。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button button = findViewById(R.id.myButton);
        button.setOnClickListener(new ButtonClick());
    }

    class ButtonClick implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            // do something
        }
    }
}  

这种方式的优点是它有助于组织代码。你可以轻松地折叠这个内部类,忘记它,直到你需要查看它。 另一个很好的理由是它可以在公共课程中转向并在其他应用领域中重复使用。

Fourth way

第四种方式涉及Activity来实现OnClickListener

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button button = findViewById(R.id.myButton);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // do something
    }
}  

这种方式的第一个缺点是在Activity中创建一个公共方法,并且在调用this时应该传递setOnClickListener活动。 避免这种方式的第二个原因是,如果添加了另一个按钮,您应该确定单击了哪个按钮。那么你应该使用switch()if()语句。它不会执行,因为它会为每个按钮点击浪费一个或几个周期。 这种方式的最后一个缺点是难以组织一个班级。在示例中,您有一个实现多个接口的Activity。突然,这些接口中的所有方法都交织在一起,在您为某些接口添加方法后,这一点变得更加明显。此外,您现在无法添加名为onClick的方法的接口。

这些方式之间存在一些差异,但您应根据自己的代码和需求选择自己的方式

以上是关于Android onClickListener实现最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Android的OnClickListener的三种实现方式

XML 中的 Android onClick 与 OnClickListener

Android 通过实现View.OnClickListener接口来实现对点击事件的相应所出现的憨批问题

当 OnClickListener.onClick 中出现 NullPointerException 时 Android 冻结(其他任务无法启动)

Android RecyclerView OnClickListener 没有反应

Android中点击事件的四种写法详解