So my question is as I am getting started with Hilt, do we need to mark all activities with #AndroidEntryPoint annotation or can we just create a BaseActivity and extend it to AppCompactActivity and mark that single class as the entry point?
Will this work? and what, if any, are the drawback of this style.
Thanks.
I'm not sure if this is a comprehensive answer, maybe it's more of a personal opinion, but I'd ask what's the goal?
Are you trying to reduce boiler plate/amount of code you need to write? Then I'm afraid it'll be the same if not more, since you'll have to go to every activity and add the inheritance part.
The downside to me is that you're now using inheritance to implement something that was avoiding it. Annotations give you the opportunity to annotate any activity without saying it's a base activity. This is often better than inheritance since not every activity is a base activity and you decouple your code more from what dagger is actually doing. I think this is more of a delegate pattern or maybe more like a decorator.
That said, to answer your question, I'm not 100% this works, but to me it has the downsides of using inheritance for something that should not be modelled by inheritance.
You cannot mark a "base class" as an AndroidEntryPoint if it is abstract, so this idea would not work anyway. As there is usually one Activity per App (recommended by google), you should not make your life harder than it is. Just annotate an Activity with #AndroidEntryPoint and you are done here.
as the document says:
Classes that Hilt injects can have other base classes that also use
injection. Those classes don't need the #AndroidEntryPoint annotation
if they're abstract.
Related
In the Using Dagger in your Android app codelab tutorial they use an activity scoped regular class that acts as a ViewModel like so
#ActivityScope
class RegistrationViewModel #Inject constructor(val userManager: UserManager) {
...
}
That makes ViewModel injection by Dagger very simple but won't we loose anyting if we don't derive from the architecture components ViewModel class?
In general, the code labs are related to some topic and they try to explain only this topic. Here it is Dagger, not Architecture Components. Yes, you can lose some functionality, but if they still can make their point - it does not matter.
Also if they make the app work with only plain java objects it means that they don't need the extra functionality from the ViewModel, they wrote less code so even better.
I also want to point out that the explanation that "you are losing ViewModel.onCleared" is "the smallest problem". What is the "main feature" of the VM is that you can share the same instance through the life cycle of the same Activity/Fragment or that you can share it between different Activity/Fragment.
And onCleared is something that should be used with caution because it means in some situations that you are trying to clear a reference to a thing you should not be holding in the first place.
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.
I'm creating an Android app and want to comply to clean architecture.
For example, I have an activity which has a presenter which creates use cases. In that inner layer, I have a repository interface (which is known by the use cases) which is implemented by a concrete repository, lets call it repsoitoryImpl (which is not known by the uses cases). What I did in previous projects was to create the presenter and the repositoryImpl in the activity, and pass the repositoryImpl as a repository to the presenter. The presenter can then, whenever there is an action coming from the activity (e.g. a button press) create a new use case and pass the repository to it.
This works, but a) the constructors of the use cases can become very long and b) the UI has knowledge of all other "outer" things, e.g. the repositoryImpl. So I thought DI to the rescue! And started to try out Dagger 2. However, my current solution does not seem to be "correct". What I would have liked is that I can just have an #inject annotated repository in a usecase and a repositoryImpl gets injected. However I found that, at the beginning of the "injection chain" I have to call inject() on the dagger component. In most of the examples, this is done in the activity. But then I would have to inject the presenter in the activity and the usecase into the presenter to be able to inject things into the use case. Is this correct? The problem is that I want to create the use cases dynamically with different parameters and not inject them.
So my current solution is to have the dagger "AppComponent" as a static field in the Android Application class and then in my use cases I call
Application.component.inject(this)
which allows me to inject things in the use case. But then the use cases have a dependency to dagger which doesn't comply to clean architecture. Because framework dependencies should only appear in the outer layer.
Is there a common solution to this problem? Am I understanding something wrong?
As u already pointed out in clean architecture use cases must not know about DI frameworks - even decorating use cases with framework specific attributes would be a smell.
As discussed here: How to handle UseCase Interactor constructors that have too many dependency parameters in DDD w/ Clean Architecture? having too many constructor parameters is usually an indicator that the use case is "doing too much". U should consider splitting them.
Furthermore the interfaces used by a use case to access "the details" (repository, external services and systems) should be designed in a way that they are most convenient for the use case. That means instead of having multiple repository interfaces and multiple service interfaces passed to a use case u could consider using façade pattern and design one or two interfaces which are more convenient for the use cases which then "aggregate" the work with the different repositories/services. This will also reduce the number of parameters passed to the constructor.
According to clean architecture the "composition" of ur application happens in the "main component" - a class living in the frameworks circle. There are objects are created and injected. If u want to create use cases dynamically u could have a factory pattern.
Which one is better option for application or activities?
A. BaseActivity class, [OR]
B.Singleton class.
In my application most of activities do same actions like show toasts, maintaining sessions, static variables,show EditText errors, HTTP request/response, etc., For now I'm extends BaseActivity in all my Activities where needed.
You're on the right path, a BaseClass is preferred because most of those thing you mentioned (Manipulating Toasts, EditText functions) require a Context to work with. A Singleton class would need that Context passed to it with every method call - a BaseClass does not (since it is technically a Context itself).
These are two fundermental different design patterns.
BaseActivity --> Inheritance
Use a Singleton in all activities --> Aggregate pattern
You find many posts in the internet about advantage and disadvantage of both patterns.
For your specific problem I would suggest to use inheritance. It is a common way to do and you should avoid to use the singleton pattern if possible.
And which way is better?
Let me know if the question needs clarification.
For reusing passing the context is easier as you then can simply copy it to another project. Otherwise you have to change all the MyActivity.this to OtherProjectActivity.this.
But most of all it doesn't matter what you use
I have chosen to answer my own question, not because any of the answers are bad, but because while they are equally good, none provide a complete answer.
It seems that one of the main factors to take into consideration is reusability:
Using MyActivity.this to refer to the context means that you will have to modify your code if you ever decide to use the class in another project/class/context.
Passing the context in the constructor and referencing it as a private variable, allows you to reuse the class wherever you want without modifications.
Another factor that will influence your choice is whether your inner class is public or it is private. It doesn't make sense to make an inner class public and then reference the context with MyActivity.this. The application would force close the moment you use the class from another activity. I would argue though, that a public class belongs in its own file, but that is up to the individual developer.
Lastly there is the matter of simplicity, as it is simpler to write MyActivity.this than to implement a constructor etc. This seeming simplicity can come back and bite you, as you can see above, if you decide you need to use the class somewhere else.
I will continue to use MyActivity.this out of simplicity for all inline eventhandlers, but for any other situation it seems that passing the context to the constructor is best practice.
This is more of a design issue as having a reference either way will have the same result. Consider the complexity, the access level and other design elements related to the inner class.