是否可以创建一个二级类来保存 OnClick 侦听器?意味着不在 Activity 类中创建?
我只是发现将 OnClick 侦听器放在主要活动类中很麻烦,我宁愿将它们放在单独的类中。谢谢
是否可以创建一个二级类来保存 OnClick 侦听器?意味着不在 Activity 类中创建?
我只是发现将 OnClick 侦听器放在主要活动类中很麻烦,我宁愿将它们放在单独的类中。谢谢
当然,这是可能的。只需创建一个实现View.OnClickListener
并将其设置为View
. 例如:
public class ExternalOnClickListener implements View.OnClickListener {
public ExternalOnClickListener(...) {
// keep references for your onClick logic
}
@Override public void onClick(View v) {
// TODO: add code here
}
}
然后将上述类的一个实例设置为监听器:
view.setOnClickListener(new ExternalOnClickListener(...));
参数化构造函数是可选的,但很可能您需要传递一些东西才能真正使您的onClick(...)
逻辑正常工作。
不过,匿名实现一个类通常更容易使用。只是一个想法。
onCLicklistener
您为什么不尝试在onClickListener
外部定义,而不是将其放在单独的类中onCreate()
?
例如:像这样
onCreate()
yourViewName.setOnClicklistener(listener):
在 onCreate() 之外
private OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
};
是的你可以。然而,将监听器设为内部类有一个优势——它可以直接访问活动类的字段和变量。如果你将它设为一个单独的类,并且你的监听器实际上需要访问 5 个视图,你的监听器构造函数可能如下所示:
MyListener listener = new MyListener(context, button, textView1, textView2, ratingBar, imageView);
这也有点笨重。如果您的听众很简单,请继续将其设为单独的类。否则,它取决于您的可读性。
让我分享一下我是如何使用 MVP 进行编码的。这是编写干净代码的最佳方式。请记住,每个类都必须有一个接口来控制它。我会告诉你一个最简单的。
假设您想在 onClick 上 Toast 一个文本并从另一个类控制它。这是它的工作原理。创建接口只是为了相互连接,您可以轻松地查看代码。
为该 MainActivity 类创建一个接口。
public interface MainActivityView {
void showToast();
}
为 Presenter 类创建另一个接口。
public interface IMainPresenter<V extends MainActivityView> {
/*Generic Type is to make sure it comes from MainActivity class only and to avoid other class to access it.*/
void onAttach(V mainView);
void onButtonClick();
}
请记住,接口只不过是覆盖每个类的方法。
创建演示者类
public class MainPresenter<V extends MainActivityView> implements IMainPresenter<V> {
private V mainActivityView;
@Override
public void onAttach(V mainActivityView) {
this.mainActivityView=mainActivityView;
}
public V getView() {
return mainActivityView;
}
@Override
public void onButtonClick() {
getView().showToast(); //This is the method from MainActivity controlling with this class
}
}
我将跳过 activity_main.xml 布局,因为只有一个 id="@+id/buttonId" 的按钮。在 MainActivityClass 中,
public class MainActivity extends AppCompactActivity implements MainActivityView {
Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainPresenter mainPresenter = new MainPresenter();
mainPresenter.onAttach(this);
btn = findViewById(R.id.buttonId);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mainPresenter.onButtonClick(); //Here, check No.3 again!
}
});
}
@Override
public void showToast() {
Toast.makeText(this, "Hello", Toast.LENGTH_SHORT).show();
}
}
我只想告诉你的是。如果在类中创建对象,则无法进行单元测试。这就是为什么您没有看到任何新对象在 android 中调用。因此,您可以在 Presenter 类中使用单例模式(这里是惰性类型)。我将删除它的界面和通用以清楚地看到它。
public class MainPresenter {
private static final MainPresenter mainPresenter = new MainPresenter();
MainPresenter() {}
public static MainPresenter getInstance() {
return mainPresenter;
}
//Some methods here can be get it once you create an object with getInstance();
}
所以你可以像这样从 MainActivity 获取它的方法。而不是创建这样的对象......
MainPresenter mainPresenter = new MainPresenter();
你可以像这样得到它...
MainPresenter mainPresenter = mainPresenter.getInstance();
可以在此处找到更多单例模式示例, https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples
最后,使用静态不是一个很好的选择,因为无论你使用与否,它都会占用内存空间。因此,您可以在 Application Layer 中创建对象,并通过 Typecasting 获取它。我确定您不需要对该应用程序层进行单元测试。
public class AppLayer extends Application {
private MainPresenter mainPresenter;
@Override
public void onCreate() {
super.onCreate();
mainPresenter = new MainPresenter();
}
public MainPresenter getMainPresenter() {
return mainPresenter;
}
你需要在 manifest.xml 中的 Application 中给出一个类名
<application
android:name=".AppLayer"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
</application>
你可以像这样在 MainActivity 中使用 Typecast 来获得它!
MainPresenter mainPresenter = ((AppLayer)getApplication()).getMainPresenter();
你能行的。但是只是认为您不会引用活动,也不会引用它的属性,包括所有视图。(除非您将它们公开或使用 getters 方法访问)。
此外,在存储对活动或侦听器上任何成员的引用时要格外小心,因为它们可能会避免垃圾收集器取回侦听器内存。
public class CommonClick {
public static void commonClick(final AppCompatActivity context){
context.findViewById(R.id.appbar).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
}