Dagger2 using Scope - android

I use Dagger2 for android project
I have 2 scopes: ActivityScope and FragmentScope
I read some sample code and they say that define and use ActivityScope so the object will be destroyed with activity lifecycle. And because Activity and Fragment have different lifecycle, so we should have 2 scopes.
My question is:
Do I need to do something to let the code know that when I use ActivityScope, object should be destroyed with the activity lifecycle? Or the code automatically knows that when I build dagger and inject to Activity like this
((DeezFoodzApplication) getApplication()).getAppComponent().inject(this);

Do I need to do something to let the code know that when I use ActivityScope, object should be destroyed with the activity lifecycle?
No. The garbage collector will take care of it (unless you store it in some static variable).
Dagger doesn't know anything but how to create or inject your objects. It does not care about lifecycle, when or where you inject / create your objects, or how you store your components. There is no magic going on, ther is no service running, or some other hack involved. Components are just some java classes that know how to fill those fields in your Activity with objects. That's all.
If you don't store the component, it will be garbae collected after its use.
If you store the component in a field of your Activity / Fragment, it will be garbage collected with the Activity / Fragment after onDestroy
If you store the component in some static variable or pass it somewhere long-living then it will stay there until you null it or that object gets garbage collected. (Also your Activity / Fragment would probably leak) Avoid storing components in static variables.
It's just a normal object like any other, try not to overthink it. You can always check the generated source code or debug it as well.

Related

remove references from memory

I'm using dagger 2 for dependency injection in my android app project.
and the question is how to remove references from component when the activity dies ?
I've read some documents about custom scopes and i've created a custom scope called #ForActivity, so references that have this annotation on them will remove when activity dies, but they don't.
any suggestions on this problem ?
If your component shares the lifecycle of the Activity—that means create the component in onCreate, store it in the Activity itself—it will be garbage collected along with the Activity at the end of the Activities lifetime.
If on the other hand you put a component that references the Activity in some way in a static variable, or some other longer lived object, you will create a memory leak. This is the only thing to keep in mind.
Nothing will be magically "removed" since Dagger just generates POJOs that handle object creation for you. Usually it is enough to just let the GC do its job.
Scopes just group dependencies and define relationships, but in the end your component is just an object that holds more objects. The Garbage Collector will remove it along with the Activity and everything else if you don't create memory leaks as mentioned above.
I recently also gave 2 detailed answers about scopes / activities / scoped objects, where you find more concrete examples on how to work with scopes / activites:
Dagger 2 Scopes, where to place Presenters?
Dagger 2 with MVP, avoid creating extra presenter object on view recreation

Best way to keep object reference in Activity through screen orientation changes

The only way that I see is to use a static variable, but it's not okay as I want to keep the ability to start multiple Activites.
In my case, I want to keep a reference of Dagger 2 Component.
It will provide objects like Navigator. I can't just store it into Bundle.
For now, I can't use Retain MainFragment instead of MainActivity because of this bug.(I'm at 23 API level)
Is there any Retain Activity implementation?
Huh, well you have two built in solutions in android to fix this problem:
1) If the object is serializeable or parcelable you can override onSaveInstanceState() and read the value out in onCreate. Here are the google developer docs for the specifics on that.
2) If your object is not serializable you can instead override onRetainNonConfigurationInstance() and return that object. You can then get the object back in onCreate. Look at this SO post for how to use this approach (don't persist your activity though! persist the object.). The drawback of this is that you can only persist one object at a time.
I have a more in depth write up of these two approaches and third, declarative approach that you can roll. It relies on onRetainNonConfigurationInstance and allows you to use annotations to declare what variables in your activity should be persisted. check it out here. That said, I wouldn't recommend using this unless you have more than one non-serializeable/parcelable object to persist.
Edit: clarified point that you shouldn't persist your whole activity using onRetainNonConfigurationInstance().

Dagger 2 lifecycle of a component, module and scope

I've read a lot of posts and tutorials about dagger 2:
http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2
http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android/
https://github.com/konmik/konmik.github.io/wiki/Snorkeling-with-Dagger-2
What determines the lifecycle of a component (object graph) in Dagger 2?
etc.
But I am still confused about the lifecycle of a component, and how it relates to module and scope. I want to make sure I don't create multiple instances of an object when I only want a Singleton. Hope someone can shed some light on these:
What's the lifecycle of a component that's built in the application class?
What's the lifecycle of a component that's built in the Activity or Fragment class?
If I want a singleton instance from a component, do I must annotate the component with #Singleton or a custom made scope and build that component in the application class?
If I build a component in the application class, does that mean all the object instances available through this component will be a singleton instance throughout the app until the app is killed or restarted?
I have a component with a custom scope let's say #ActivityScope, and I build that component in an Activity, will the object instances injected through this component be destroyed automatically after this activity's onDestroy() is called?
Again I have a component with a custom scope let's say #ActivityScope, and I build this component in ActivityA and ActivityB, will ActivityA and ActivityB share the same object instances from this component or they will have their own instances of the same object?
How I understand it:
And keep in mind two things (when I first read 1) it it made everything cleaner to me):
1)Components live as long as you want it to or as long as class that created component wasn't destroyed (like android activity or fragment)
2)If you don't annotate you provide methods with annotation (must be the same as component annotation) new objects will be created every time you request for them
What's the lifecycle of a component that's built in the application class?
Component built in application class lives as long as you want. I mean you can create it at any time and remove it at any time as long as you create it in class that extends android Application class (this way component object will live as long as your Android App is running) in contrast to component that's built in activity class - it will live as long as activity is alive so it may be destroyed for example on orientation change.
Keep in mind that if for some reason you didn't create your ApplicationComponent in onCreate() method of Application class (for example you created it later when something happened) it can be destroyed (nulled) when Android OS is low on memory and user closed your app, and then when user comes back to your app (to last visible activity) when it has been killed earlier and you ask your app component to do something then check if it's not null
What's the lifecycle of a component that's built in the Activity or
Fragment class?
I partially answered it in above answer. If you create your component inside Fragment/Activity it lives as long as you want or as long as activity or fragment is not destroyed due to orientation change or low memory
If I want a singleton instance from a component, do I must annotate
the component with #Singleton or a custom made scope and build that
component in the application class?
It depends where you want to use this singleton. If you want singleton in single activity you may create for example #ActivityScope annotation and annotate provide methods and ActivityComponent with this annotation, then you create your ActivityComponent inside onCreate() Activity method and you have a singleton as long as your activity lives (it may be helpfull if you plan to have a singleton shared between different fragments from same activity).
If you want singleton between different acctivities/fragment in app the best way to do that would be to create it in AppModule and annotate provide method and app component with singleton annotation.
If I build a component in the application class, does that mean all
the object instances available through this component will be a
singleton instance throughout the app until the app is killed or
restarted?
If you annotate provide methods with #Singleton annotation then yes
I have a component with a custom scope let's say #ActivityScope, and I
build that component in an Activity, will the object instances
injected through this component be destroyed automatically after this
activity's onDestroy() is called?
Yes
Again I have a component with a custom scope let's say #ActivityScope,
and I build this component in ActivityA and ActivityB, will ActivityA
and ActivityB share the same object instances from this component or
they will have their own instances of the same object?
They will have their own instances

Dagger2 Component as Static Global Variable

My Android app has multiple activities. The MainActivity constructs a Dagger2 component in its onCreate() method and assigns it to a static variable so any class can call the static method MainActivity.getDaggerComponent() to then inject itself with dependencies.
The problem I'm discovering is that when I start up my VideoPlayerActivity, the MainActivity object sometimes gets its onPause() invoked. If this happens, the static component variable gets set to null. At a later point, VideoPlayerActivity needs to inject its dependencies, but there is no component so things blow up.
How does one ensure that a Dagger2 component is available at all times for all activities?
Initialize Dagger component in Application class or just statically. It might be that you're doing a very wrong thing trying to use dependencies of one Activity in another Activity. This might create memory leaks and in particular sounds like a design problem. What if your first Activity was already destroyed? Who will free up the Dagger instance? Why graph belongs to first Activity and not to the second one? What if user will enter your app from the second Activity - then first one won't be even initialized. And so on, and so on.
If you still need Activity instance, then you should use Activity specific component within the Activity and move everything else in global (Application wide) component.

Does RoboGuice re-instantiate previously existing objects when onCreate() is called

My Activity is injected with a number of objects that are initialized
before onCreate is called for the first time.
When my Activity finishes by invoking the finish method, it passes
through onDestroy before returning to the main "OS desktop" window.
I then invoke my application again, and onCreate is again called.
This time though my view remains the same as when finish was initially
called above.
Therefore, I am wondering if RoboGuice re-instantiates the injected
objects again? If not, is there a way for me to do this?
Thanks.
are you saying that these are not re-instantiated then?
when onCreate() is called ex. when you change phone orientation every object are injected once again. But if one of injected object is Singleton, the same instance of object will be injected. "Singleton" works in scope of whole application so the activity lifecycle does not ifluence on signleton objects.
Take a look at the Android activity lifecycle docs.
If onCreate is called by Android then a new instance of your activity was created and any non-singleton components will be instantiated, and all components will be injected by roboguice.
If you only need a single instance of a component you can make it a singleton. Just be cautious of memory use with singletons because they will live for the duration of the application process. So even if an activity has been destroyed but your app process is still running those singletons will be consuming memory.
Roboguice is just a wrapper around guice. If you are interested in pursuing other options for getting instances of classes take a look at Bindings, Scopes and Providers in guice.

Categories

Resources