Open lexer opened 10 years ago
My approach is to pass resources through the Module that defines the Screen's scope:
@dagger.Module(injects = ScreenView.class, //
addsTo = MainFlow.Module.class, //
)
/* package */static final class Module {
@Provides @Named("title") String provideTitle(Activity activity) {
return activity.getString(R.string.title);
}
}
I resolve the Activity
dependency though the MainFlow.Module
, since the Activity
creates it, it can pass itself to the constructor.
I should add, that then allows you to provide them in the @Inject constructor of the Presenter
. My original attempt, and an alternative option, is to use the View
(in Presenter.onLoad()
): getView().getResources().getString(R.string.title)
. You'd notice that that would happen on every load, so that led me to storing the value in the Bundle
in Presenter.onSave()
and reuse it. That felt silly, and then I realized I already had the Activity
dependency.
Any reason not to just define a provider for resources at the application module level, then inject the resources object?
@technicalcycling plays hell with unit testing of presenters, and in particular seems sometimes to lead to battles between Robolectric and Mockito.
@imminent Making it possible to inject the Activity seems very dangerous. We tend to make our Application instance available via injection, but even then rarely use it directly. I'll typically do something like:
class MyScreen implements Blueprint {
interface Supplies {
CharSequence title();
CharSequence moarText();
}
//...
@Singleton Presenter extends ViewPresenter<MyView> {
final Supplies supplies;
@Inject Presenter(Supplies supplies) {
this.supplies = supplies;
}
}
@dagger.Module class MyModule() {
Supplies provideSupplies(final Resources resources) {
return new Supplies() {
final CharSequence title = resources.getString(R.string.title);
final CharSequence moarText = resources.getString(R.string.moarText);
CharSequence title() { return title; }
CharSequence moarText() { return moarText; }
};
}
}
}
And then I wish for Kotlin to reduce the boilerplate.
Leaving this open as a reminder to document or sample this somewhere.
@lexer to get at the Activity intent I think I'd do something like:
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
MortarScope appScope = Mortar.getScope(getApplication());
activityScope = Mortar.requireActivityScope(appScope, new ActivityBlueprint(this));
activityScope.getObjectGraph().inject(this);
activityScope.onCreate(savedState);
}
class ActivityBlueprint implements mortar.Blueprint {
final Intent activityIntent;
final String name;
ActivityBlueprint(Activity activity) {
name = activity.getClass().getName() + "-task-" + activity.getTaskId();
activityIntent = activity.getIntent();
}
@Override public String getMortarScopeName() {
return SquareActivity.this.getMortarScopeName();
}
@Override public Object getDaggerModule() {
return new Module();
}
@dagger.Module class Module {
@Provides Intent provideActivityIntent() {
return activityIntent;
}
}
}
Or better yet make the ActivityModule provide some actual model objects described by the intent rather than the raw intent itself..
Is it dangerous if the ObjectGraph
that injects the Activity
has the
same lifecycle as the Activity
?
Dandré Allison (323) 823-4456 KeepandShare.com http://www.keepandshare.com
Schedule & Share. Simply. Securely.
On Thu, Mar 27, 2014 at 9:52 AM, RayFromSquare notifications@github.comwrote:
@technicalcycling https://github.com/technicalcycling plays hell with unit testing of presenters, and in particular seems sometimes to lead to battles between Robolectric and Mockito.
@imminent https://github.com/imminent Making it possible to inject the Activity seems very dangerous. We tend to make our Application instance available via injection, but even then rarely use it directly. I'll typically do something like:
class MyScreen implements Blueprint { interface Supplies { CharSequence title(); CharSequence moarText(); }
//...
@Singleton Presenter extends ViewPresenter
{ final Supplies supplies; @Inject Presenter(Supplies supplies) { this.supplies = supplies; } } @dagger.Module class MyModule() { Supplies provideSupplies(final Resources resources) { return new Supplies() { final CharSequence title = resources.getString(R.string.title); final CharSequence moarText = resources.getString(R.string.moarText);
CharSequence title() { return title; } CharSequence moarText() { return moarText; } }; }
} }
And then I wish for Kotlin to reduce the boilerplate.
Leaving this open as a reminder to document or sample this somewhere.
Reply to this email directly or view it on GitHubhttps://github.com/square/mortar/issues/45#issuecomment-38829991 .
@imminent it's standard practice. Updated the snippet above to demonstrate.
It's unclear what is the best way to obtain resources (strings drawables etc) and activity intent. Can add this to sample please.