web-dev-qa-db-ja.com

Android:あるアクティビティから別のアクティビティにインターフェイスを送信する方法

私はこのようなインターフェースを持っています:

public interface MyInterface {
    public void aMethod();
}

私のカスタムオブジェクト:

public class MyObject {

    private Context context;
    private MyInterface inter;

    public MyObject(Context context) {
        this.context = context;
        this.inter = (MyInterface) this.context;
        inter.aMethod();
    }
}

主な活動:

public class MainActivity extends Activity implements MyInterface {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyObject my = new MyObject(this);

    }

    @Override
    public void aMethod() {
        Toast.makeText(this, "done", Toast.LENGTH_SHORT).show();
    }
}  

ここでは、MyObjectコンストラクター内で、コンテキストからインターフェイスを取得し、Activityと通信できます。

ただし、あるアクティビティから別のアクティビティにインターフェイスを送信するにはどうすればよいですか?
Activity2からActivity1内のメソッドを呼び出す必要があります
このような方法はありますか?

注:フラグメントを使用したくない。

25
palatok

何よりもまず、これは非常に悪いことです。

this.inter = (MyInterface) this.context;

インターフェイスを実装していないコンストラクターにコンテキストを渡すと、アプリケーションがクラッシュし、そのような間違いを犯しやすくなります。したがって、これは非常にエラーが発生しやすいので、代わりに次のように実装してください。

public class MyObject {

    private Context context;
    private MyInterface inter;

    public MyObject(Context context, MyInterface inter) {
        this.context = context;
        this.inter =  inter;
        inter.aMethod();
    }
}

このように、はるかに安全でクリーンです。


Objectを別のActivityに送信するには、Serializableが次のように実装されていることを確認してください。

public interface MyInterface extends Serializable {
    public void aMethod();
}

そして今、あなたは他のIntentを開始するActivityに追加としてインターフェースを追加することができます:

Intent intent = new Intent(context, OtherActivity.class);
intent.putExtra("interface", inter);
startActivity(intent);

OtherActivityでは、ObjectからIntentを次のように取得できます。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = getIntent();
    MyInterface inter = (MyInterface) intent.getSerializableExtra("interface");

    ...
}

編集:

Activityで次のようなことをすると、匿名クラスが作成されます。

OnCreateListener inter = new OnCreateListener() {

    @Override
    public void onObjCreate() {
        Log.d("pltk", "dfgbfdgh");
    }
};

このような匿名クラスに関することは、静的クラスではないということです。つまり、このリスナーがネストされているクラスのメソッドや変数に引き続きアクセスできます。内部的にこの理由は、この新しいクラスがそれを作成したクラスのインスタンスへの参照を保持しているためです。あなたのケースでは、Activityを囲みます。これは素晴らしいことであり、OnClickListenerなどに常に使用します。しかし、あなたの場合、このObjectを別のActivityに送りたいので問題です。古いActivityへの内部参照は、シリアル化されないようにします。これは良いことです。そのようなObjectを送信することができれば、ガベージコレクターが収集できないすべての古い参照のために、狂ったようなメモリリークが発生します。

解決策は非常に簡単です。独自のファイルでクラスを定義するか、クラスを静的にすることができます。このコンテキストでの静的とは、クラスが本質的にそれ自身の別個のファイルにあるように扱われ、そのため、囲んでいるクラスのインスタンスにアクセスできないことを意味します。

そのため、あなたがしなければならないことをまとめると、クラスをネストしたままにして、次のように静的に定義することです。

public class YourActivity extends Activity {

    private static class OnCreateListenerImpl implements OnCreateListener {

        @Override
        public void onObjCreate() {
            Log.d("pltk", "dfgbfdgh");
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_palatok);

        OnCreateListener inter = new OnCreateListenerImpl();
        Intent in = new Intent(Palatok.this, SecondActivity.class);
        in.putExtra("ob", inter);
        startActivity(in);
    }
}

または、独自の個別のファイルで実装を移動できます。

public class OnCreateListenerImpl implements OnCreateListener {

    @Override
    public void onObjCreate() {
        Log.d("pltk", "dfgbfdgh");
    }
}

OnCreateListenerを別のActivityに送信したい理由はまだわかりませんが、これで問題が解決するはずです。

お役に立てば幸いです。さらに質問がある場合はお気軽にお問い合わせください。

42
Xaver Kapeller

可能ですが、このような種類のアクティビティ<->アクティビティの相互作用により、メモリリークが発生します。代わりにLocalBroadcastManager( http://developer.Android.com/reference/Android/support/v4/content/LocalBroadcastManager.html )を使用する必要があります。

3
Stepango