У меня есть приложение Mortar с MortarActivityScope в качестве первого дочернего элемента в корневой области. MortarActivityScope имеет 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
не заменяет модуль из старой области действия новым модулем, предоставленным новым Blueprint. Вместо этого граф объектов сохраняет ссылку на предыдущий модуль, включая уничтоженную Activity.
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);
}
}
Пример активности Mortar, кажется, обходит это, не включая метод @Provides Activity
в основной модуль. Но разве MortarActivityScope
не может внедрить активность? Каков предпочтительный способ сделать это, не теряя все ваши одноэлементные объекты (объекты Presenter
и т. д.) при изменении ориентации?