5

ルート スコープの下の最初の子として MortarActivityScope を持つ Mortar アプリケーションがあります。MortarActivityScope には、注入されたクラスのアクティビティを @Provides する ActivityScope があります。

@Module(addsTo = ApplicationModule.class, injects = {Foo.class, SomePresenter.class, AnotherPresenter.class})
public class ActivityModule {

    private final Activity activity;

    public ActivityModule(Activity activity) {
        this.activity = activity;
    }

    @Provides Activity provideActivity() {
        return activity;
    }
}

public class Foo {
    private final Activity activity;
    @Inject(Activity activity) {
        this.activity = activity;
    }
    public void doSomethingWithActivity() {
       // do stuff with activity: findViewById(), getWindow(), mess with action bar etc.
    }
}

これは、向きの変更が発生するまでは問題ありません。Mortar サンプル プロジェクトでは、向きが変わってもアクティビティ スコープは破棄されません。これはおそらく、@Singleton プレゼンター、スクリーンなどを向きの変更後も保持できるようにするためです。これは、サンプル プロジェクトのメイン アクティビティの onDestroy() メソッドで確認できます。

@Override protected void onDestroy() {
    super.onDestroy();

    actionBarOwner.dropView(this);

    // activityScope may be null in case isWrongInstance() returned true in onCreate()
    if (isFinishing() && activityScope != null) {
      MortarScope parentScope = Mortar.getScope(getApplication());
      parentScope.destroyChild(activityScope);
      activityScope = null;
    }
  }
}

ただし、このようにすると、向きが変わっても古い ObjectGraph が存続することになります。Mortar.requireActivityScope古いアクティビティ スコープのモジュールが、新しいブループリントによって提供される新しいモジュールに置き換えられないことがわかりました。代わりに、オブジェクト グラフは、破棄されたアクティビティを含む、前のモジュールへの参照を保持します。

public class MyActivity extends Activity implements Blueprint {

    @Inject foo;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MortarScope parentScope = Mortar.getScope(getApplication());
        activityScope = Mortar.requireActivityScope(parentScope, this);
        Mortar.inject(this, this);

        foo.doSomethingWithActivity(); //fails, because activity injected by object graph is destroyed
    }

    @Override
    public String getMortarScopeName() {
        return getClass().getName();
    }

    @Override
    public Object getDaggerModule() {
        return new ActivityModule(this);
    }
}

@Provides ActivityMortar サンプル アクティビティは、メイン モジュールにメソッドを含めないことで、これを回避しているようです。しかしMortarActivityScope、Activity を注入できるべきではありませんか? 向きの変更時にすべてのシングルトン オブジェクト (Presenterオブジェクトなど) を失うことなく、これを行うための推奨される方法は何ですか?

4

1 に答える 1

5

安全にすることができないアクティビティを注入することを誰にも許可しないでください。代わりに、アクティビティに関連付けられているプレゼンターを挿入します。

Mortar で onActivityResult() を処理する方法には、プレゼンターを所有するアクティビティの例が含まれています。他のプレゼンターを含むアプリの他の部分は、それを挿入して、アクティビティを処理する必要があることを何でも実行するように要求できます。

また、すべてのアクティビティ固有の作業を 1 つのアクティビティ プレゼンターに結び付ける必要はありません。私たちのアクティビティには、そのサービスをアプリの残りの部分に仲介するプレゼンターがいくつかあります。

于 2014-10-23T22:55:30.877 に答える