web-dev-qa-db-ja.com

Android-別のクラスのOnClickリスナー

OnClickリスナーを保持するセカンダリクラスを作成することはできますか? Activityクラスで作成されていないという意味ですか?

OnClickリスナーをメインアクティビティクラスに配置するのは面倒で、別々のクラスに配置する方がいいと思います。ありがとう

28
Pztar

もちろん、それは可能です。 _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(...)ロジックを機能させるために何かを渡す必要がある可能性が非常に高くなります。

ただし、クラスを匿名で実装すると、一般的に作業が簡単になります。ちょっとした考え。

30
MH.

onCLicklistenerを別のクラスに置く代わりに、なぜonCreate()の外でonClickListenerを定義しようとしないのですか?

例:このように

onCreate()

yourViewName.setOnClicklistener(listener):

onCreate()の外側

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

        }
    };
10
Renjith

はい、できます。ただし、リスナーを内部クラスにすることには1つの利点があります-アクティビティクラスのフィールドと変数に直接アクセスできることです。別のクラスにして、リスナーが実際に5つのビューにアクセスする必要がある場合、リスナーコンストラクターは次のようになります。

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

これもちょっとかさばります。リスナーが単純な場合は、先に進んで別のクラスにします。それ以外の場合は、読みやすさはあなた次第です。

5
Lawrence Choy

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. プレゼンタークラスを作成する

    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. Id = "@ + id/buttonId。"のボタンだけがあるため、activity_main.xmlレイアウトはスキップします。 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クラスでシングルトンパターン(ここではレイジータイプ)を使用できます。明確に見るために、そのインターフェースとGenericを削除します。

    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. 最後に、静的を使用するかどうかは、使用するかどうかにかかわらずメモリスペースを使用するため、あまり良い選択ではありません。そのため、アプリケーション層内でオブジェクトを作成し、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 Principlesを学ぶことをお勧めします。きれいなコーディングを作成するのに役立ちます。楽しんでください!
1
Dracula Oppa

できます。ただし、アクティビティへの参照は持たず、すべてのビューを含む属性への参照も持たないと考えてください。 (gettersメソッドで公開またはアクセス可能にしない限り)。

また、アクティビティまたはリスナーのメンバーへの参照を格納する場合は、ガベージコレクターがリスナーのメモリを取り戻すことを回避できるため、特に注意してください。

1
Robert Estivill
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) {

            }
        });
    }
}
0
nithin joseph