-
Notifications
You must be signed in to change notification settings - Fork 8
Best way to inject dependencies into Fragment provided by parent Fragment / Activity #4
Comments
Hi @ubuntudroid, can you maybe provide a small example project reproducing this issue? It's easier for me to "think" in code :) |
In the meantime I tried it out myself in the example application. Please have a look here and especially here. Basically it boils down to the situation mentioned in your first point. The I know this is not ideal. Maybe you, I or someone else comes up with a better idea? |
Regarding your point with Glide. If you configure Glide instances in modules so that they are tied to the |
If you don't want to delegate certain dependencies to child components, like for example a class MainActivity : AppCompatActivity(),
KatanaTrait {
override val component = createComponent(
modules = listOf(...),
dependsOn = listOf(...)
)
private val myComponent = createComponent(
modules = listOf(createGlideModule(this)),
dependsOn = listOf(component)
}
private val glide: GlideApp by myComponent.inject()
} I'm thinking of maybe providing a simplified syntax for creating child components, something like val childComponent = component.plus(listOf(childModule))
// or
val childComponent = component + listOf(childModule) |
Wow, that was a quick and super extensive response! 😮 First of all thanks for the Fragment sample code - that really helps a lot in determining how the canonical way of injecting with Katana is. 🙏 Further musings regarding your suggestions/samples and my own previous statements: Thinking more about what Unfortunately
Therefore I guess your "lazy component" + "lateinit injected properties" + "depends On" approach seems to be the only feasible solution here for now. I still don't particularly like that part of katana to be honest, maybe I'll come up with another solution after using it a bit more. |
Btw, AFAIK you could remove the |
Actually this is possible with I must admit that I'm not using Fragments in the project that I created Katana for. I'm using Conductor. Conductor's But I think we'll find a satisfying solution for Fragments, too. |
Oh wow, I should have tried overriding myself. 🤦♂️ I was so sure that it would not work - sorry for that! I see your point - using Fragments certainly makes this a bit more complicated than with a purely View based app. There are different reasons why we keep on using Fragments (one of those is: we are using Google's Architecture Components which work nicely with Fragments). I'll keep on experimenting with the |
@ubuntudroid I updated the second Fragment example with an alternative approach. Here I created a
Also version 1.2.7 of Katana contains the new syntax as you can see in the example. |
@svenjacobs Thanks for including the new syntax! 😍 While I like the idea of resolving dependencies in the module, I am a bit unsure whether I really like the container approach, especially the need to now call Regardless of that, how would you handle potential overrides with that approach? Let's take the common case of a parent Fragment + child Fragment again. Both specify |
Dependencies that should be "inherited" are put into the public component whereas everything that should not be inherited or could cause overrides is put into a private component. See my other comment. With the new syntax this is even easier now ;) |
@svenjacobs thanks for the clarification - I think I got that now. 🤓 Will hopefully be able to play around a bit with it tomorrow and come back with my findings. The only thing that feels strange already is that we now have that primary first-class component from the |
Unfortunately interfaces cannot declare private or protected properties. Everything must be public. Of course I could create a |
Ah yeah, of course, protected doesn't work in interfaces - what about switching the interface to an abstract class instead? |
Disregard that - as we have no multi-inheritance this would not work either in most classes and make the whole library a lot less flexible. 🤔 |
I was just about to say that 🙂 |
So I think we now have a few working solutions for the problem mentioned in this issue. Someone will probably come up with something even better in the future, but for now I guess we can close the issue. Thanks a million for your super active support, mate! 🔝 🙏 |
Glad I could help 🙂 If you have any further questions feel free to create a new issue or contact me via Slack. Looking forward to your opinion when you're using Katana in your production application 😎 |
In version 1.2.8 of Katana I added KatanaFragment and KatanaFragmentDelegate to the Android artifact. These utility classes should simplify usage of Katana with Fragments a bit. Also see the updated demo application. |
In Android DI you quite often share dependencies between Fragments via the parent Fragment or the Activity.
Katana allows to define
dependsOn
components. One would think, that you would just use that:But there are multiple problems with this:
by lazy {}
create the component or create it inonAttach/onCreate
. That in turn means that we would need to eitherby lazy { injectNow() }
all injections in the Fragment or manually set them inonAttach/onCreate
as well.bind<Glide>
per Fragment module which becomes awkward when having child Fragments as you have to name all those binds. Similar things can happen with nestedNavHostFragments
s and the accordingNavController
s.An alternative which solves 2, but not 1 is to specifically inject stuff provided by the parent Fragment/Activity within the (child) Fragment module. Thus we can omit any potential overrides as we don't want them in the Fragment anyway:
But this somehow feels a bit strange as well as I suddenly exactly define from where I want to get my dependencies supplied. That part just feels more ioc with the
dependsBy
approach.Any best practises here?
The text was updated successfully, but these errors were encountered: