Is it mandatory to add #AndroidEntryPoint annotation on all dependent classes like fragment dependent upon activity. Is there any alternative solution for overcome this exception?
Just add #AndroidEntryPoint to your parent Activity class:
And yes, it's a mandatory process if you want to use Hilt. You could use Dagger to get away with this.
Related
Why we must to annotate activities which contains fragments on it ?
Activity has no #Inject but fragments need some dependencies .
I annotate fragments as #AndroidEntryPoint but crash until set this on parent activity.
You can't start a Fragment without an Activity. You have to annotate your Activity with #AndroidEntryPoint because your fragment is a HiltComponent now. When you don't annotate your Activity with #AndroidEntryPoint Hilt would not create a component for this activity and thus could not start the fragment because it didn't create the ActivtyComponent yet.
Hilt activities need to be attached to Hilt applications. Hilt
fragments must be attached to Hilt activities.
See here: https://dagger.dev/hilt/migration-guide (2. Migrate Activities and Fragments)
Why should I use viewmodelproviders for viewmodels?
Why I just can't add custom singleton annotation to my viewmodel, and then inject this viewmodel to fragment class?
Like so:
#MainScope
class MainViewModel #Inject constructor(): ViewModel()
And then:
open class BaseFragment<T: ViewModel>: DaggerFragment() {
#Inject
protected lateinit var viewModel: T
Both cases are independent of screen rotation.
Is there any drawbacks of singleton annotation case?
I see only advantages, with this approach I don't need to copy/paste tons of code.
Why should I use viewmodelproviders for viewmodels?
To get viewModel.onCleared() callback called properly at the right time by the ComponentActivity.
(and to ensure it's created only once for the given ViewModelStoreOwner).
Why I just can't add custom singleton annotation to my viewmodel, and then inject this viewmodel to fragment class?
Because you won't get viewModel.onCleared() callback called properly at the right time by the ComponentActivity.
Is there any drawbacks of singleton annotation case? I see only advantages,
That you don't get viewModel.onCleared().
Also if you have a singleton variant, then the ViewModel won't die along with its enclosing finishing Activity, and stay alive even on back navigation (which is probably not intended).
with this approach I don't need to copy/paste tons of code.
You're using Kotlin. Use extension functions.
I have a doubt regarding Dagger 2.
I have a BaseFragment class in which i am writing AndroidSupportInjection.inject(this), and all my fragments are extending from this Fragment class. I also have a FragmentBuilder class where i mention all the Fragments using #ContributesAndroidInjector annotation where i need injection to happen.
My doubt is, if in a Fragment i don’t need any dependency still i have to mention it in my FragmentBuilder class because its extending from BaseFragment. Is it a all right to do so or this will lead to any memory leak or is this a wrong design pattern ?
Please help!!
In your situation i'll go with 2 "base" fragments, the first BaseFragment doesn't allow injection then you make a BaseInjectableFragment that inherit from the first one and you make it injectable, this looks more cleaner this way.
So here are the things I know from the doc
Dagger Android under the hood is creating subcomponent for each Activity annotated with ContributesAndroidInjector
You can apply custom scope to the method where ContributesAndroidInjector is annotated to
If two sibling subcomponents have the same scope, they will still have different scope instances
If an Activity is in a subcomponent, it can have its own subcomponent which can contain Fragments. Those Fragments will share the scoped instances the Activity has.
Now my question is:
How to have one Activity be a subcomponent of another activity using Dagger Android?
I want to do this because I want to achieve things like #UserScope/#SessionScope.
From this I know that I can do it with just Dagger not Dagger Android. But with Dagger Android, you can only have the Application (which is the AndroidInjector) to inject Activity. You can not have an Activity used as a holder or host of the parent subcomponent to inject another Activity.
Am I understanding it correctly?
05/14/2018 Update:
I ended up getting rid of Dagger Android. So no more ContributesAndroidInjector, just pure Dagger. And to inject Activity/Fragment, I use the way that's recommended here. It will be something like this:
class MyActivity : AppCompatActivity() {
private val factory: ViewModelProvider.Factory = Injector.myCustomScope().factory()
}
And we are trying to make sure the factory is the only thing that Activity/Fragment needs.
So far it's been great.
How to have one Activity be a subcomponent of another activity using Dagger Android?
tl;dr You can't. Dagger Android follows a strict AppComponent > ActivityComponent > FragmentComponent scheme and there is no way to add custom scopes in-between.
I suggest you have a look at the Dagger Android source code, it's really not that much. It's basicalle a HashMap for each layer where you look up the component builder and build the subcomponent. A fragment looks at its parent Activity, an Activity looks at the Application. There is no feature where you can add custom components between layers.
What you can do is create your own variant of "Dagger Android" where you can implement your own interfaces and mix/match components as you need them. But that's quite a bit of extra work. I created a #PerScreen scope that survives configuration changes as a proof of concept if you are interested to see how you could do such a thing.
You can create a custom Scope called for example #PerScreen, also you will have #PerActvity scope. The difference between these scopes is that the #PerActivity scope will maintain shared dependencies between all activities like Context, Layout Inflater, etc. And all activity specific dependencies will be scoped as #PerScreen.
#PerApplication -> #PerActivity -> #PerScreen
This could structured like that.
I have explained scopes under the hood in my blog post, you can refer to it to get better understanding of this matter.
i have been using RoboGuice dependency injection with a Activity and a Fragment Activity. But i cannot figure out how i can use it using a fragment as we dont call setContentview in the Fargment. Can anyone show me an example of how to use this ?
Kind Regards
Here's a post that describes the solution. Main steps are:
Extend RoboFragment.
Return a root View from onCreateView().
Use #InjectView annotations the same way you do in RoboActivity.