ルート スコープの下の最初の子として 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オブジェクトなど) を失うことなく、これを行うための推奨される方法は何ですか?