Skip to main content

Dagger Multibindings saved my time



While the Android architecture made development simpler, we should always be aware of the Lifecycle and with that, the right way to provide ViewModels. Creating one ViewModel factory for each Fragment and ViewModel you have is really expensive, bad architecture, and too much unnecessary code.  Not to mention the fact that you should care about scopes, dependencies, components modules when using Dagger for DI.

You can have a simple "generic" ViewModel factory for all your app as a Singleton, with the help of Kotlin Reflection and Daggers Multibinding.

What is provided here is a class, which has a Map in the constructor and extending the ViewModelProvider.Factory. On the only method it has, we are just going to provide our own instance of the ViewModel we need, which is the key of the map, and when that dependency is available we are going to require its particular dependencies which are "stored" in the value of that map. We can place as many ViewModels as we need, and this will be achieved by Dagger Multibinding. So it's just a Map<SomeViewModels, AndSomeViewModeldependencies>. The dependencies cannot just appear directly, so with the help of Provider<T> they arrive on the moment the ViewModel has just started. The @JvmSuppressWildcards is just making sure that the explicit Provider<ViewModel> will be on the Java generated files.

To put what we need on that map, Dagger has a nice way of doing it. First, you need to create an annotation which will pass the key to the map:

For example: To access HomeViewModel dependencies, we need a key, which happens to be the class itself. After that, what is needed is just to "put" those ViewModels in the map:

Remember, we are in @Singleton scope (although in the example using a custom annotation, personal preference). So, where are the values (dependencies) for each key provided? They just appear when the ViewModel is instantiated. And that's amazing about how Dagger solves DI problem in the Java/Kotlin/Android world:

And when injecting a ViewModel factory:

Remember, all this work is not done just for a Repository, each ViewModel implementation might have different dependencies.

Conclusion:

Having tons of ViewModels in your Android app might make it too hard and expensive to produce them. When using Dagger Multibindings (if you are using dagger at all) it's a lot easier and prevents from writing bad code. Furthermore, if you want to add another Fragment and ViewModel, it's just like a game.

Popular posts from this blog

Modularizing your Android app, breaking the monolith (Part 1)

Inspired by a Martin Fowlers post about Micro Frontends, I decided to break my monolithic app into a modular app. I tried to read a little more about breaking monolithic apps in Android, and as far as I got, I felt confident to share my experience with you. This will be some series of blog posts where we actually try to break a simple app into a modularized Android app.

Note: You should know that I am no expert in this, so if there are false statements or mistakes please feel free to criticize, for the sake of a better development. 

What do you benefit from this approach:
Well, people are moving pretty fast nowadays and delivery is required faster and faster. So, in order to achieve this, modularising Android apps is really necessary.You can share features across different apps. Independent teams and less problems per each.Conditional features update.Quicker debugging and fixing.A feature delay doesn't delay the whole app. As per writing tests, there is not too much difference about…

From Gson to Moshi, what I learned

There is no doubt that people are getting away from GSON and I agree with those reasons too. The only advantage GSON has over other parsing libraries is that it takes a really short amount of time to set up. Furthermore, the most important thing is that Moshi is embracing Kotlin support.

First let's implement the dependency:
implementation("com.squareup.moshi:moshi:1.8.0") It's not a struggle to migrate to Moshi. It's really Gson look-a-like. The only thing to do is annotate the object with @field:Json instead of @SerializedName (which is Gsons way for JS representation):

data class User( //GSON way @SerializedName("name") val name: String, @SerializedName("user_name") val userName: String, @SerializedName("last_name") val lastName: String, @SerializedName("email") val email: String ) data class User( //Moshi way @field:Json(name = "name") val name: String, @field:Json(name = "user_name…

Modularizing your Android app, breaking the monolith (Part 2)

This is part 2 of a series of articles about modularizing Android app. If you haven't yet read the first article, you may find it here.

On our first article we just moved some classes outside the application and applied as an independent module. But what if we have dependencies pulled from the application level? This could be a small challenge. First of all, we want to clarify on how are we going to modularize the app. And depending on the previous article, I chose the by feature version of modularization. First of all, let's show some dependencies that are going to be needed in the whole app.

Note: I'm using Dagger for handling dependencies but manual DI or any dependency tool should be fine to understand this part.

So, this is my dependency schema:


Well, it's not that bad, but this isn't what we want to transform to when trying to modularize the app. If you think about it, modules that don't need a dependency, can get it quite easily. For example: A FeatureXVi…