30

是否可以创建一个二级类来保存 OnClick 侦听器?意味着不在 Activity 类中创建?

我只是发现将 OnClick 侦听器放在主要活动类中很麻烦,我宁愿将它们放在单独的类中。谢谢

4

6 回答 6

33

当然,这是可能的。只需创建一个实现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(...)逻辑正常工作。

不过,匿名实现一个类通常更容易使用。只是一个想法。

于 2012-11-21T03:40:37.900 回答
11

onCLicklistener您为什么不尝试在onClickListener外部定义,而不是将其放在单独的类中onCreate()

例如:像这样

onCreate()

yourViewName.setOnClicklistener(listener):

在 onCreate() 之外

private OnClickListener listener    =   new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

        }
    };
于 2012-11-21T03:38:48.273 回答
7

是的你可以。然而,将监听器设为内部类有一个优势——它可以直接访问活动类的字段和变量。如果你将它设为一个单独的类,并且你的监听器实际上需要访问 5 个视图,你的监听器构造函数可能如下所示:

MyListener listener = new MyListener(context, button, textView1, textView2, ratingBar, imageView);

这也有点笨重。如果您的听众很简单,请继续将其设为单独的类。否则,它取决于您的可读性。

于 2012-11-21T03:39:08.780 回答
2

让我分享一下我是如何使用 MVP 进行编码的。这是编写干净代码的最佳方式。请记住,每个类都必须有一个接口来控制它。我会告诉你一个最简单的。

假设您想在 onClick 上 Toast 一个文本并从另一个类控制它。这是它的工作原理。创建接口只是为了相互连接,您可以轻松地查看代码。

  1. 为该 MainActivity 类创建一个接口。

    public interface MainActivityView {
        void showToast();
    }
    
  2. 为 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();
    }
    

请记住,接口只不过是覆盖每个类的方法。

  1. 创建演示者类

    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
        }
    }
    
  2. 我将跳过 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();
        }
    }
    
  3. 我只想告诉你的是。如果在类中创建对象,则无法进行单元测试。这就是为什么您没有看到任何新对象在 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

  1. 最后,使用静态不是一个很好的选择,因为无论你使用与否,它都会占用内存空间。因此,您可以在 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();
  1. 为了进一步的学习,我建议你学习 ButterKnife、Dagger 2 和 SOLID 原理。它将帮助您创建干净的编码。玩得开心!
于 2018-08-16T03:28:28.997 回答
1

你能行的。但是只是认为您不会引用活动,也不会引用它的属性,包括所有视图。(除非您将它们公开或使用 getters 方法访问)。

此外,在存储对活动或侦听器上任何成员的引用时要格外小心,因为它们可能会避免垃圾收集器取回侦听器内存。

于 2012-11-21T03:37:49.240 回答
0
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) {

            }
        });
    }
}
于 2019-07-17T08:42:12.137 回答