Android onClickListener实现最佳实践



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

  1. 在布局文件中设置指向活动中方法的onClick属性
  2. 创建一个匿名内部类
  3. 将onClickListener分配给私有成员变量
  4. 让"活动"上下文实现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展示了关于内存泄漏的另一个优点

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

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

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

4) 是3d的变体。

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

我从不使用onClick属性,因为它将布局与特定的"活动"联系在一起(它必须通过反射找到方法)。它对碎片不起作用。

选项2和选项3实际上完全相同。如果您想使用私有成员作为多个视图的OnClickListener,则选项3可能更有利。

备选方案4接近备选方案3。一个关键的区别是它更改了类声明,因此,如果保持类声明不包含接口实现(或者可能需要保持某种二进制兼容性)对您来说很重要,那么您可能不想使用此选项。

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

使用OnClickListener有四种方法。

第一种方式

在方法调用站点中定义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方法。当您希望从多个视图观察单击事件时,这一点会变得更加明显
避免这种情况的下一个原因是,如果几个按钮应该做同样的事情,它不会促进代码重用。

第二种方式

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

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

这种方法和第一种方法非常相似,唯一的优点是该方法可以对多个按钮重复使用。

第三种方式

这种方法是声明一个内部类来实现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
        }
    }
}  

这种方式的优点是有助于组织代码。你可以很容易地折叠这个内部类,然后忘记它,直到你需要查看它。
另一个很好的原因是它可以在公共类中打开,并在其他应用程序领域中重复使用。

第四种方式

第四种方法是活动来实现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
    }
}  

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

这些方法之间有一些差异,但您应该根据您的代码和需求来选择您的方法

相关内容

  • 没有找到相关文章

最新更新