I inject viewModels,repositories,fragments,Utils and ... but Is it good way to inject common class with dependency injection Koin or Dagger-hilt?
Suppose that we want to use StringBuilder() class in fragment
First approach :
We can inject it
val otherModule= module {
single { StringBuilder() }
}
And use it in fragment like this :
class Fragment : BaseFragment(){
private val mPassword : StringBuilder by inject()
}
Second approach :
We can create new instance without injection
class Fragment : BaseFragment(){
private var mPassword = StringBuilder()
}
My question is the first approach is common way for us ?
I'd say that it depends. The main goal / concept behind Di is to fulfil the firth principle of S.O.L.I.D, or as freecodecamp.org says:
It is the fifth principle of S.O.L.I.D — the five basic principles of
object-oriented programming and design by Uncle Bob — which states
that a class should depend on abstraction and not upon concretions (in
simple terms, hard-coded).
According to the principles, a class should concentrate on fulfilling
its responsibilities and not on creating objects that it requires to
fulfill those responsibilities. And that’s where dependency injection
comes into play: it provides the class with the required objects.
Another good answer is provided here, as it is already discussed when not to use dependency injection.
And now my opinion: If possible, try to inject those dependencies that you have to use quite often and if possible, inject them via constructor injection. With this, you can easily see, which dependencies are used by your class. Try not to inject classes that are used once or common language classes.
No, you wouldn't inject common language classes at all. There's no benefit to it. We inject classes when they need additional dependencies that we don't want to be creating ourselves, so we let the DI framework create them.
Related
Please someone explain me why when we use dependency injection and initialize the object in the module the provides function return type is interface but in body function we return the actual object. This is example
#Provides
#Singleton
fun providePrefsManager(#ApplicationContext context: Context): PrefsManager {
return PrefsManagerImpl(context)
}
Why here we return PrefsManager instead of PrefsManagerImpl ?
Code to the interface, not the implementation. #Provides methods provide according to their return values, so if you return PrefsManagerImpl, Dagger will only know how to inject PrefsManagerImpl. By returning PrefsManager, Dagger lets you inject PrefsManager directly, so the injecting class doesn't need to be aware of PrefsManagerImpl or any other implementation at all.
More specifically to dependency injection: The concept behind dependency injection is that, for the class you're writing, it's the caller or DI framework that controls which instance or implementation your class receives. This is an "inversion of control" compared to a self-contained class that maintains complete control of which classes or dependencies it uses.
As such, the class you're writing should be as general as possible when specifying its dependencies, which gives you flexibility about which implementations you can supply.
For example: If you need a sort algorithm, it would defeat the flexibility of dependency injection if you always asked specifically for a hypothetical MyBinarySortImpl; instead, you should make your request more general, such as injecting an interface like BinarySorter or Sorter (both also hypothetical). Your caller or dependency injection framework can still supply a MyBinarySortImpl, but by being as general as possible you also free your caller to supply a WellTestedNativeBinarySortImpl or a VeryFastRadixSortImpl. If your implementation needs to be a binary sort, you can specify that, and if it doesn't you can leave it general.
In your specific case, your #Provides method provides a binding of PrefsManager; the implementation happens to be a PrefsManagerImpl. However, the class that consumes PrefsManager is asserting that it doesn't need anything specific to PrefsManagerImpl, it can work when it only uses the interface as described through PrefsManager. That injecting class can now be tested using a FakePrefsManager or a mocking-framework-created mock(PrefsManager), or even a wrapper you could write like LoggingPrefsManager(PrefsManagerImpl(context)). By operating through interfaces rather than implementations, it keeps your options open.
I've seen many tutorials for MVVM. Most of them say that you need to define your ViewModel class like this:
class MainViewModel: ViewModel() {
...
}
But recently I stumbled upon Dagger tutorial project from Google. There is a different ViewModel class definition:
class MainViewModel(private val userDataRepository: UserDataRepository) {
...
}
So I wonder, what is the difference between these two approaches?
That's not a relevant comparison. That CodeLab uses a non-ViewModel ViewModel class to simplify their explanation of how DI works. Notice it doesn't subclass ViewModel. Also, the project starts without the dependency injection and has you add it in later, so the starting project isn't intended to be a good example of how to design something.
Either way, if you have a repository, you need some way to get a reference to the repository in your ViewModel. If it is through the constructor, you would have to get a reference to the repository in the associated ViewModelFactory that you build for this class. If you use Dagger, you'll probably let Dagger generate this factory for you and inject the reference.
If your ViewModel doesn't use a repository, then you won't have any reason to have one in your constructor, with or without dependency injection. Many basic MVVM tutorials are going to start with the most basic possible example, a ViewModel with no arguments needed. That doesn't imply that a ViewModel should never have dependencies.
To define a singleton, should I use Kotlin object declaration or to make an ordinary Kotlin class and inject it using dagger? In my opinion the first option is definitely easier but there may be a reason to use dagger in this situation that I'm not aware of.
Option 1 (notice object keyword):
object SomeUtil {
// object state (properties)
fun someFunction(number: Long) {
// ...
}
}
Option 2 (notice class keyword):
class SomeUtil {
// object state (properties)
fun someFunction(number: Long) {
// ...
}
}
#Module
class AppModule {
#Provides
#Singleton
internal fun provideTheUtil() = SomeUtil()
}
class MainActivity : BaseActivity() {
#Inject internal lateinit var util: SomeUtil
}
UPDATE 2019-07-03
#Blackbelt said in comments that we should prefer option 2 for testability. But libraries like MockK can mock objects too. So do you still think option 2 is the preferred one?
You might want to reconsider the need of NumberFormatUtil being a singleton. It might be cheaper if you use #Reusable with Dagger or even a factory without any scope directly.
If NumberFormatUtil is fairly simple and only provides a few utility methods, no state and no need for mocking in tests, you could use an object implementation, maybe using #JvmStatic for Java-inter-operability. But then you could go for global utility (extension) functions as well:
package xyz
fun formatNumber(number: Long) {
// ...
}
fun Long.format() = formatNumber(this)
You should use option 2.
In software engineering, the singleton pattern is a software design
pattern that restricts the instantiation of a class to one "single"
instance. This is useful when exactly one object is needed to
coordinate actions across the system.
From: Singleton Pattern
So, a singleton is single instance in a scope. In case of Android, it is virtual machine instance running the app. In case you need custom scopes, you have to use option 2 only.
But, if you have only static methods inside the object you want to inject its better to keep them as global methods and even get rid of object. No need to inject anything. It is similar to a java class with only static methods (I mentioned this point as it is a usual way of creating Utility classes).
However, if the object also has some state. I would recommend going dagger way. The object way does not provide with dependency injection. It only creates a Singleton. Your purpose for using dagger is dependency injection.
I believe that I should inject everything. (So we can discuss it also)
I used a recycleview and added a dividerItemDecoration or LinearLayoutManager
so in my ActivityModule.java
public class ActivityModule {
private AppCompatActivity mActivity;
public ActivityModule(AppCompatActivity activity) {
this.mActivity = activity;
}
#Provides
DividerItemDecoration provideDividerItemDecoration() {
return new DividerItemDecoration(mActivity, DividerItemDecoration.VERTICAL);
}}
I provide my DividerItemDecoration like that.
and on my fragment I just inject
#Inject
DividerItemDecoration itemDecorator;
and use it like :
itemDecorator.setDrawable(Objects.requireNonNull(getDrawable(getBaseActivity(), R.drawable.language_separator)));
It is okay for a fragment.
PROBLEM :
I can use DividerItemDecoration next time in another fragment as Horizontal.. and I can not provide DividerItemDecoration again again.
I want to create general method or something . I will inject to my fragment for example
#Inject
DividerItemDecoration itemDecorator(horizontal???).. ?
I do not know how its syntax and logic.
How to provide and inject that kind of codes?
Waiting your supports.
Also it is a native view stuff, Maybe It can not need to inject.. Please tell your opinions.. I remind you that still I need an example and to learn for that kind of methods injection and providing..
Thanks a lot
I want to share a text about Dependency Injection, It makes us to change our mind using dependency injection :
Do not (always) use DI: Injectables versus newables
Something that was immensely useful to me when learning about DI
frameworks was the realisation that using a DI framework does not mean
that you have to DI to initialise all of your objects. As a rule of
thumb: inject objects that you know of at compile time and that have
static relations to other objects; do not inject runtime information.
I think this is a good post on the subject. It introduces the concept
of 'newables' and 'injectables'.
Injectables are the classes near the root of your DI graph. Instances
of these classes are the kind of objects that you expect your DI
framework to provide and inject. Manager- or service-type objects are
typical examples of injectables. Newables are objects at the fringes
of your DI graph, or that are not even really part of your DI graph at
all. Integer, Address etc. are examples of newables. Broadly speaking,
newables are passive objects, and there is no point in injecting or
mocking them. They typically contain the "data" that is in your
application and that is only available at runtime (e.g. your address).
Newables should not keep references to injectables or vice versa
(something the author of the post refers to as
"injectable/newable-separation").
In reality, I have found that it is not always easy or possible to
make a clear distinction between injectables and newables. Still, I
think that they are nice concepts to use as part of your thinking
process. Definitely think twice before adding yet another factory to
your project!
We decied to remove injection of ArrayList, LinearLayoutManager, DividerItemDecoration. We created these classes with "new" not inject
We can inject same class with #Named
#Provides
#Named(CMS.Client.DELIVERY_API_CLIENT)
fun provideCMSClient(): CDAClient {
return CDAClient.builder()
.setSpace("4454")
.setToken("777")
.build()
}
#Provides
#Named(CMS.Client.SYNC_API_CLIENT)
fun provideCMSSyncClient(): CDAClient {
return CDAClient.builder()
.setSpace("1234")
.setToken("456"))
.build()
}
So I am currently in the process of learning dagger 2, and from the tutorials that I've read so far, for a dependency to be injected, the #Inject annotation gets placed inline with fields (for Activities/Fragments) or constructors. However I see that as an issue if I'm not the owner of parts of the code and can't add the required annotations for this technique to work, or if I don't want other parts of the code to know that dagger exists.
The application structure I have at the moment is:
App Module - where I'd like to put my DI code in (e.g. dagger modules, etc).
Presentation Module - Views/ViewModels etc.
Domain Module - Use Cases etc.
Data Module - Repositories etc.
With pretty much this style of classes contained in my application:
class ExampleViewModelImpl(useCase: ExampleUseCase): ViewModel() in Presentation (gets initialised from an Activity or similar).
class ExampleUseCaseImpl(repository: ExampleRepository): ExampleUseCase in Domain
class ExampleRepositoryImpl(dao: ExampleDao): ExampleRepository in Data
With the structure above, what is the minimum number of classes outside of the App Module that I need to touch in order to utilize dagger with as much automated dependency injection as possible? Code examples of how this is achieved would be great.
I am unsure of some terminologies, and wasn't able to find a solution online. If there are good resources which explains what I'm asking, that would also be great.
if I don't want other parts of the code to know that dagger exists.
#Inject is a standard (JSR 330) which Dagger implements. Adding those annotations doesn't have anything to do with Dagger and can be used the same way with other DI frameworks. If it's your code you should just add those #Inject annotations where appropriate. Think of them as documentation: What constructor/field/method must be injected to create & use this object?
The only place where your classes will know that Dagger exists is at the same place where you'd be creating the objects otherwise, too.
Going down that path, of course you could use Dagger without any #Inject annotations, but you'd be writing a lot of unnecessary boilerplate and missing out on the most powerful feature of Dagger at the same time (code generation).
#Inject annotation gets placed inline with fields (for Activities/Fragments) or constructors. However I see that as an issue if I'm not the owner of parts of the code and can't add the required annotations for this technique to work
That's what #BindsInstance with the #Component.Builder is for (add an object to the component) and what #Provides annotated methods are for (create and initialize an object from a module)
If you really want to write code without #Inject, then you'd do exactly this for all of your objects. This means a lot of modules, and even more #Provides annotated methods. It will work, but I don't see the point in writing all those methods if a single #Inject on the constructor has the same effect.
In my opinion the best thing about Dagger is that I can add / remove / change constructor parameters and don't have to touch any other parts of my code since Dagger will generate new code with the new arguments. In your case you'd have to also change the parameters to the #Provides method as well as the constructor invocation.
Next let's look at how to remove #Inject from fields. Basically you don't want to do field injection, so instead of writing an injection method in the component, you'd write provision methods.
#Component
class MyComponent {
fun inject(activity: MyActivity)
}
class MyActivity {
#Inject lateinit var myDep: Dependency
fun onCreate() {
component.inject(this)
}
}
Removing the #Inject we need to use the provision methods instead.
#Component
class MyComponent {
fun provisionMyDependency() : Dependency
}
class MyActivity {
lateinit var myDep: Dependency
fun onCreate() {
myDep = component.provisionMyDependency()
}
}
It will work and everything, but again, you will miss out on the single best feature of Dagger: Code generation. The example above looks alright because I only added a single dependency, but think about what happens to those 2 different implementations when you add / remove / change dependencies, how well it will scale. If you prefer to do things manually any refactoring will become arduous.
With the structure above, what is the minimum number of classes outside of the App Module that I need to touch in order to utilize dagger with as much automated dependency injection as possible?
Your question (especially the title) is in direct conflict with your goal. If you don't want to use those annotations, then you can't use Dagger code generation & injection but have to resort to do it manually as highlighted above.
with as much automated dependency injection as possible
To best utilize Dagger you add #Inject on the constructor and/or fields of every class that should end up on your dependency graph and let Dagger do its thing.