Android - OnClick Listener在一个单独的类中

时间:2012-11-21 03:31:07

标签: android class onclicklistener

是否可以创建一个二级类来保存OnClick侦听器?意义没有在Activity类中创建?

我只是发现在主活动类中放置OnClick监听器只是凌乱,我宁愿将它们放在不同的类中。感谢

6 个答案:

答案 0 :(得分:29)

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

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

答案 1 :(得分:10)

不要将onCLicklistener放在单独的类中,为什么不尝试在onClickListener之外定义onCreate()

例如:像这样

<强>的onCreate()

yourViewName.setOnClicklistener(listener):

外部onCreate()

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

        }
    };

答案 2 :(得分:5)

是的,你可以。但是,使侦听器成为内部类有一个优点 - 它可以直接访问活动类的字段和变量。如果你把它作为一个单独的类,并且你的监听器实际上需要访问5个视图,那么你的监听器构造函数可能如下所示:

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

这也有点笨重。如果您的听众很简单,请继续将其作为单独的课程。否则,由您提供可读性。

答案 3 :(得分:1)

你可以做到。但只是认为你不会参与活动,也不会参考它的属性,包括所有视图。 (除非您将它们公开或使用getter方法访问)。

另外,要特别注意存储对活动或侦听器上任何成员的引用,因为它们可能会避免垃圾收集器重新获取侦听器内存。

答案 4 :(得分:0)

让我分享一下我如何使用MVP进行编码。这是编写清晰代码的最佳方法。请记住,每个类都必须具有控制它的接口。我将向您展示最简单的一个。

假设您要烘烤文本onClick并从另一个类控制它。运作方式如下。创建界面无非是要相互连接,您可以轻松查看代码。

  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. 创建Presenter类

    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().onToast(); //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 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. 最后,使用静态不是一个很好的选择,因为无论您是否使用它,它都会使用内存空间。因此,您可以在应用程序层中创建对象,并通过类型转换将其获取。我确定您不需要对该应用程序层进行单元测试。

    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 Principles。这将帮助您创建简洁的编码。玩得开心!

答案 5 :(得分: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) {

            }
        });
    }
}