アダプターからのActivityメソッドの呼び出し


119

Activityfrom で定義されているメソッドを呼び出すことは可能ListAdapterですか?

(私が作りたいButtonlist's私が設定しようとしました。行と、このボタンがクリックされたときに、それが活動の対応で定義されている方法を実行する必要がありonClickListener、私の中でListAdapter、私はそのパス何、このメソッドを呼び出す方法を知りません。 ..)

使用したときにActivity.this.method()次のエラーが発生しました:

No enclosing instance of the type Activity is accessible in scope

何か案が ?


他のクラスでは、そのアクティビティの内部クラスでない限り、activity.thisを呼び出すことはできません。@Eldhose M Babuソリューションに従ってください
Archie.bpgc

回答:


306

はい、できます。

アダプターで新しいフィールドを追加します。

private Context mContext;

アダプターコンストラクターに次のコードを追加します。

public AdapterName(......, Context context) {
  //your code.
  this.mContext = context;
}

アダプターのgetView(...):

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
    if (mContext instanceof YourActivityName) {
      ((YourActivityName)mContext).yourDesiredMethod();
    }
  }
});

コードやアクティビティなどが表示される独自のクラス名に置き換えます。

この同じアダプタを複数のアクティビティに使用する必要がある場合は、次のようにします。

インターフェースを作成する

public interface IMethodCaller {
    void yourDesiredMethod();
}

このメソッド呼び出し機能を使用するために必要なアクティビティにこのインターフェイスを実装します。

次に、アダプターのgetView()で、次のように呼び出します。

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mContext instanceof IMethodCaller) {
            ((IMethodCaller) mContext).yourDesiredMethod();
        }
    }
});

完了です。この呼び出しメカニズムを必要としないアクティビティにこのアダプターを使用する必要がある場合、コードは実行されません(チェックが失敗した場合)。


29
これはよくある質問なので、このソリューションは使用しないことを強くお勧めします。これはランタイム例外を引き起こす可能性があるため、ここでのクラスのキャストは避けてください。
イゴールフィリッポフ2014年

3
Eldhose兄弟、私はあなたに対して何もしませんが、以下の答えがベストプラクティスです。コメントで読むこともできます。コードの再利用を避けるため、mContextをアクティビティにキャストしないでください。このアダプターは、mContext変数をキャストしたアクティビティ内でのみ使用できます。リスナーを定義している場合は、同じアダプターを別のアクティビティで再利用できます。私が業界で十分な時間を費やしてきました、私はここであなたを助けようとしているだけだと信じてください。個人的にそれを取らないでください。
Varundroid、2014

2
このソリューションは、私がSOで見つけた中で最高のものの1つです。バブさん、ありがとうございました。これによってアクティビティのメソッドを呼び出すと、アプリ全体で500%のキックパフォーマンスが向上します->アクセスする必要があるアダプターにデータベースを再ロードする必要はありません。私は「業界での年」を気にしません。安定して機能するソリューションを探しています。アクセスするためのより良い方法を見つけることはできません。おそらく、DBをシングルトンとして設定することもできますが、これはプロジェクトを「構造化解除」する方法ではありません。
Martin Pfeffer、2015年

2
@RAM複数のアクティビティで同じメソッドを呼び出す必要がある場合は、そのメソッド名でインターフェースを作成する必要があります。次に、メソッド呼び出しを利用するために必要なすべてのアクティビティにそのインターフェイスを実装します。次に、クリックリスナーで、アクティビティ名を使用するのではなく、インターフェースのインスタンスを確認します。
Eldhose M Babu

1
素晴らしい答え。親指アップ
Alok Rajasukumaran

126

あなたはこの方法でそれを行うことができます:

インターフェースの宣言:

public interface MyInterface{
    public void foo();
}

あなたの活動にそれを盛り込ませてください:

public class MyActivity extends Activity implements MyInterface{
    public void foo(){
        //do stuff
    }
}

次に、アクティビティをListAdaterに渡します。

public MyAdapter extends BaseAdater{
    private MyInterface listener;

    public MyAdapter(MyInterface listener){
        this.listener = listener;
    }
}

そして、アダプターのどこかで、そのActivityメソッドを呼び出す必要がある場合:

listener.foo();

5
私は最初にフラグメントと同じように上記の方法を考えましたが、これが最善の解決策です!
Brux 2013

1
私のInterfaceListenerは何ですか?どのように初期化できますか?public MyAdapter(MyInterface listener){this.listener = listener; }
Gilberto Ibarra 2014年

6
(アクティビティから)インターフェースをアダプターにどのように渡しますか
Brandon

1
渡すことができる@Brandonは、アダプターのコンストラクターパラメーターです。
Igor Filippov

5
@Brandon、 'this'を追加して、インターフェースをアダプターに渡しますmyAdapter = new MyAdapter(this);
ajinkya

67

元の:

私は現在の答えを理解していますが、より明確な例が必要でした。Adapter(RecyclerView.Adapter)とで使用した例を次に示しActivityます。

あなたの活動で:

これにより、にあるが実装さinterfaceれますAdapter。この例では、ユーザーが内のアイテムをクリックすると呼び出されますRecyclerView

public class MyActivity extends Activity implements AdapterCallback {

    private MyAdapter myAdapter;

    @Override
    public void onMethodCallback() {
       // do something
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myAdapter = new MyAdapter(this);
    }
}

アダプターで:

Activity、を開始し、Adapterこれを引数としてコンストラクタに渡しました。これによりinterface、コールバックメソッドが開始されます。ユーザークリックにコールバックメソッドを使用していることがわかります。

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private AdapterCallback adapterCallback;

    public MyAdapter(Context context) {
        try {
            adapterCallback = ((AdapterCallback) context);
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement AdapterCallback.", e);
        }
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int position) {
        // simple example, call interface here
        // not complete
        viewHolder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    adapterCallback.onMethodCallback();
                } catch (ClassCastException e) {
                   // do something
                }
            }
        });
    }

    public static interface AdapterCallback {
        void onMethodCallback();
    }
}

6
このおかげで、それはまさに私が探していたものです。賛成票
Nactus

これは私のために働いた!imo、これまでで最も完全に機能するコード!
publicknowledge 2016

2
この解決策をありがとう
Steve

4
この回答には、より多くの賛成票が必要です。それは、クリーンで完璧なソリューションです。
Opiatefuchs 2016年

こんにちは@Jared- EventBusあなたが提案したのと同じサンプルを修正できますか?
Tohid

15

基本的でシンプル。

アダプターでこれを使用してください。

((YourParentClass) context).functionToRun();


4
クラスを制限して、クラスではなくYourParentClass型のみで機能するように制限しているが、それを再利用する必要がない場合は機能し、クラスの名前も変更するとコードが壊れる...
Gustavo Baiocchi Costa

7

もう1つの方法は次のとおりです。

アダプターにメソッドを記述して、public void callBack(){}と言います。

ここで、アクティビティーでアダプターのオブジェクトを作成するときに、このメソッドをオーバーライドします。アダプタでメソッドを呼び出すと、オーバーライドメソッドが呼び出されます。

Myadapter adapter = new Myadapter() {
  @Override
  public void callBack() {
    // dosomething
  }
};

5

Kotlinの場合:

アダプターで、単に呼び出す

(context as Your_Activity_Name).yourMethod()

0
if (parent.getContext() instanceof yourActivity) {
  //execute code
}

活動が持っている場合、この条件は何かを実行することができますGroupViewから要求することを望むgetView()あなたの方法adapterですyourActivity

注:parentそのGroupView


このGroupViewは、getView()メソッドを呼び出すときにアダプターからのビューを要求します。そのため、そのGroupViewのコンテキストを取得し、上記の条件でそれを調べます
Abd Salam Baker

0

Kotlinでは、ラムダ関数を使用することにより、インターフェイスを必要としない、よりクリーンな方法があります。

class MyAdapter(val adapterOnClick: (Any) -> Unit) {
    fun setItem(item: Any) {
        myButton.setOnClickListener { adapterOnClick(item) }
    }
}

class MyActivity {
    override fun onCreate(savedInstanceState: Bundle?) {
        var myAdapter = MyAdapter { item -> doOnClick(item) }
    }


    fun doOnClick(item: Any) {

    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.