I want to use Dagger on Android to inject an instance of an Activity
into another class as follows:
class PresentationLayer{
Activity mActivity;
@Inject
public PresentationLayer(Activity activity){
this.mActivity = activity;
}
public void presentData(User user){
((TextView)mActivity.findViewById(R.id.username))
.setText(user.getName());
//...
//...
}
}
I am able to do the injection, but all fields of the Activity
are null
at the time of injection.
Here's how I am doing the injection:
My Activity
is a module in itself.
@Module(
complete = false
)
class MainActivity extends Activity{
@Override
public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.main_activity);
ObjectGraph objectGraph = CustomApplication.getObjectGraph();
PresentationLayer pres = objectGraph.get(PresentationLayer.class);
}
@Provides Activity provideActivity(){
return this;
}
}
This is my main module
@Module(
entryPoints = PresentationLayer.class,
includes = MainActivity.class
)
class DaggerModule{
@Provides PresentationLayer providePresentation(Activity activity){
return new PresentationLayer(activity);
}
}
And my Application
class that bootstraps the object graph.
class CustomApplication extends Application{
private static ObjectGraph sObjectGraph;
@Override
public void onCreate(){
sObjectGraph = ObjectGraph.create(new DaggerModule());
}
static getObjectGraph(){
return sObjectGraph;
}
}
I am looking for a way to explicitly perform the injection after I call setContentView
.
How do I go about doing this?
I got it to work like this - however I am not sure if this is the "right way". What I do is
Module
constructorObjectGraph
after I do setContentView()
so that a proper Activity
instance is passed in to the ObjectGraph
.My Activity
is no longer a dagger Module
.
This translates to the following in code:
@Module(
entryPoints = PresentationLayer.class
)
class DaggerModule{
private Activity mActivity;
public DaggerModule (Activity activity){
this.mActivity = activity;
}
@Provides PresentationLayer providePresentation(){
return new PresentationLayer(mActivity);
}
}
And this is how my Activity
looks:
class MainActivity extends Activity{
@Override
public void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.main_activity);
ObjectGraph objectGraph = CustomApplication.getObjectGraph(this);
PresentationLayer pres = objectGraph.get(PresentationLayer.class);
User user = //get the user here
pres.presentData(user);
}
}
This solution seems to address the points raised by Jesse Wilson in this answer. However, I am concerned about the performance, since the ObjectGraph
is going to be built every time the Activity
is created.
Any thoughts?
To inject an object in the activity, you'd use the appComponent defined in your Application class and call the inject() method, passing in an instance of the activity that requests injection.
Dagger automatically generates code that mimics the code you would otherwise have hand-written. Because the code is generated at compile time, it's traceable and more performant than other reflection-based solutions such as Guice. Note: Use Hilt for dependency injection on Android.
Dependency injection provides your app with the following advantages: Reusability of classes and decoupling of dependencies: It's easier to swap out implementations of a dependency.
Dagger is a fully static, compile-time dependency injection framework for Java, Kotlin, and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Unfortunately this probably isn't going to work with Dagger, or with most other dependency injection frameworks. The problem is that the lifecycle of Activity
doesn't cleanly line up with the lifecycle of PresentationLayer
. For example, when you rotate your screen, Android will destroy the activity and create another one in its place. There's no hook for PresentationLayer
to participate in that.
At Square we've been using Otto to communicate between activities and their backends and it has worked well. See Eric Burke's sample code project for an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With