Dagger 2, injectiong UI elements - android

Is it possible to inject some UI elements such as AlertDialog and ProgressDialog that needs Activity for initializing? Initializing them with Application not working of course and also we cannot create Singleton dependency using Activity (because of the reference to destroyed activity)

Yes, Dagger don't differentiate orinary and lifecycle classes, but you should store Dagger component inside Activity or Fragment to avoid memoty leaks. Those instances will be singletons only inside your component.

Related

How it impact on memory if I create all View Models with Activity scope?

I'm using new Android architectural components : MVVM, LiveData, etc. As recommended by Android documentation as well as in many blogs, in order to share data between fragments, we should create SharedViewModel which will be accessed by each fragment using ViewModelProviders with Activity scope.
I just want to know, Is there any impact on memory, if I create all my ViewModels with Activity scope?
Do they automatically destroyed on Android low memory?
No you should aware about memory issue.
In the navigation AAC, Google recommands single activity application.
But that is hard in some part.
So I use separated activity to using same view model scope.
If a, b, c must use same Viewmodel, just make a A Activity for them and separate with d, e fragment(in B Activity).
Using shared ViewModel is common when your fragments communicating with each other or should use the same data, Not for all separated fragments.
Using a single ViewModel for all fragments is a bad practice and further impact on memory, decrease code simplicity and makes your ViewModel to a God object that decides for all other components.
It's normal that each activity/fragment have its own ViewModel, and manage its own data and ViewModel lifecycle.

Dagger2 using Scope

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.

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