In the context of developing and android app, should I use presenters directly in views using 'new' or would it be better if I injected them to the view.
Pros/cons for not using injected presenters:
Faster development time, without having to write components and modules.
Presenters are tightly coupled with the views, I don't see this as much of a problem as most of the time presenters are not shared across multiple views(ie. one single view for a presenter).
Might be a problem for testing, as with using dependency injection mock implementations of the presenters can be provided(not sure if this is any useful, need more insight on this).
You're right. Using injection will only help you in the long run. You could either spend 5 minutes setting up your module / component, or you could be just coding.
As long as you don't do proper testing, there is not much difference to it, if you presenter looks like the following
mPresenter = new Presenter();
Assuming you use constructor injection properly, after creating your component, you save some lines as compared to
#Inject Presenter mPresenter;
// onCreate or some other place
{
getComponent().inject(this); /* getComponent() also 4-5 lines */
}
Again. If you use proper constructor injection there is a good chance you don't have many module code. Just creating some component will do.
But you saved some minutes and once you want to do testing this is just some easy refactoring, which can quickly be done.
So why Dagger?
This was assuming your presenter has no dependencies on other objects. But what if it does?
SharedPreferences preferences = getPreferences();
MyStorage storage = new MyStorage(preferences);
mPresenter = new Presenter(storage);
Using something to store your data is properly a good use case. While you just added some more logic about object creation to your activity, the dagger implementation would still look the same.
Even more?
Now let's assume you want to share this storage from above between activities. Now you have to add some logic to your Application or in some other place where you can create a Singleton to use throughout your app.
This will probably not be your only singleton, though, and you will start to clutter up your Application as well. Don't get me started on managing those objects lifecycle, e.g. user logging in or out, make sure to clear that cached data!
Again. The dagger implementation still looks the same. If there is some more logic needed it is well placed in the modules and abstracted with component dependencies.
Once you start thinking I could just create classes that handle object construction and injection you know that you could have just used dagger in the first place ;)
I also wrote a blog post about dagger basics including how constructor injection works, which many beginners are not using properly for some reason.
Related
Currently, I have a database manager class that handles all operations to the database like this:
class DatabaseManager(val context: Context) {
private val db = Firebase.firestore
//Other functions, etc.
}
It makes use of the context passed in by different activities to perform functions to the database. The thing is, every single activity that requires database functions have to instantiate this manager class first, then call the functions. I would like to make use of the Singelton design pattern to make it such that all the activities will only use a single instance of the class. I believe kotlin's objects can do this, however I also need to be able to pass in the context of the activities into this manager class. Any assistance is appreciated, thank you!
I would recommend not doing that. The problem with Singletons is that they make code hard to test, you can't fake out the database. And for a database this is a particularly bad problem, as setting up all the right fake data can be painful. Instead, take a look at injection. It can do the same thing (make a single instance shared between everyone who needs it), but it manages that global state rather than having the classes themselves manage it via a static reference, passing it in (generally via the constructor) to whoever needs it. This makes it easy to provide an alternative or mock database when needed for testing. Injection used to be a bit painful to set up, but Hilt makes it a lot easier these days.
I have one Activity and i have created one View-model for it. I have created different classes like
UiUtil( show, hide view, hide key board ), Network layer , Data Base layer, AppUtil( for common functionality like Collection check, String validation, Date Conversion etc)
My question is, In MVVM design pattern is Activity can use these utility classes directly or it needs to use these classes via View-model, if it via view model then in the view-model i have to write a method that just call utility classes method . like below TimeDateManager is utility class used in view-model
class HomeViewModel: BaseViewModel()
{
fun prepareTimeAmPmToDisplay(context: Context, alarm: Alarm): String
{
return TimeDateManager.prepareTimeAmPmToDisplay(context, alarm)
}
}
Architectures are not obligatory, they are recommendational, thus you can change their usage in quite wide range. The only stopper should be a common sense(if it is present of course).
In this particular case the usage of utility class inside an Activity maybe ok, based on your ViewModel construction and its way of communication with View(read Activity).
For example if you have some LiveData that sends some kind of event(for ex. data loaded from backend or alarm trigger) inside your ViewModel and your View listens to it, I think it is ok to use util classes inside an Observer in Activity. Especially if this utils method doesn't depend on any ViewModel or Repository data. The direct utils usage in Activity is not limited by this usecase, though - there are plenty of others.
I understand that this may be an unpopular opinion in modern time of "clean approach" but I believe that this "clean approach" sometimes complicates stuff where it shouldn't, thus if mixing things a bit does not brake overall architecture but rather makes some thing more readable and easy to maintain - I would go for it.
Hope it helps.
My approach toward MVVM is simple, ViewModel is responsible for business logic, dealing with repositories (Network, Database, etc.) and all of the non-UI codes preparing the required data for UI, just like the documentation:
A ViewModel object provides the data for a specific UI component, such as a fragment or activity, and contains data-handling business logic to communicate with the model. For example, the ViewModel can call other components to load the data, and it can forward user requests to modify the data. The ViewModel doesn't know about UI components, so it isn't affected by configuration changes, such as recreating an activity when rotating the device.
On the other hand, ViewModels should not store a context (ApplicationContext is exceptional) and it's preferred that they do not use android APIs at all, so they become more testable (especially in the case on pure unit tests).
Also we are recommended to make use of LiveData in ViewModels and the UI has to observe the LiveData. For example, in onCreate of your Activity, you will call loadMainContent() method from VM, it calls getMainContent(page=1) from repository, and the repository will decide to load data from DB or network, and the result will be set on a LiveData were the View is listening for changes.
TL;DR
Sometimes it's even better to call these utilities from View rather than the VM. I'm pretty sure about your UiUtil also I think TimeDateManager is more view related rather than logic related. In addition, Network and DB layers are more efficient if called through a repository (which is responsible for caching, etc.) and VM can use that repo.
I'm working on an Android App which follows the MVP architecture pattern. In all my fragments I'm injecting a Presenter. Therefore my Fragments (Views) need to have a Component in which I declare the injects. For example:
#ActivityScope
#Component(
dependencies = AppComponent.class,
modules = {
PresenterModule.class,
InteractorModule.class
}
)
public interface ViewInjectorComponent {
void inject(SelectEventOccurrenceFragment fragment);
void inject(CreateOpponentFragment fragment);
void inject(SelectOpponentFragment fragment);
void inject(TeammatesInvitedFragment fragment);
...
}
Every new View that I add into my App (Fragment) needs to have its entry declared here. I was wondering if It's possible to generate this code automatically with some kind of annotation processor. The App has already several fragments, this component file has easily more than 300 entries. It'd be awesome if I could do something like:
#Injectable
public class MyNewFragment implements MyNewView {
...
}
And then automatically generate the entry in the ViewInjectorComponent file. It's possible? Where should I look at?
The situation you are experiencing may be a consequence of organising your Modules and Components in an unusual way. In particular, grouping laterally (one Component injects all the Presenters) rather than vertically (one component injects the functionality related to SelectOpponentActivity) is problematic.
A good example to follow is in the Google Android Architecture Blueprints GitHub repo. If you peruse the code there, you will see that they have organised functionality related to Tasks inside one Java package together with a separate Component, Module, Presenter etc. This has the nice advantage of being able to restrict accessibility of the constructors of the classes contained therein and fulfilling Effective Java Item 13: Minimize the accesibility of classes and members.
Likewise, you've grouped all your modules together into a Presenter Module and an Interactor Module. The advice from the Dagger 2 official documentation is to organise Modules first for testability and then along functional lines. Again, you can refer to the Blueprint example for how to do this.
Finally, note that there is unavoidably some boilerplate involved in using most DI frameworks like Dagger 2. In a sense, you are exchanging a bigger problem ("how do I deal with all of these constructors?") with much smaller and more manageable problems ("how do I group my Components" etc.).
Update
There is a library called Auto Dagger2 that can generate components for you. See this Github repo. Here is an example of an annotation:
#AutoComponent
#Singleton
public class ExampleApplication extends Application {
}
Which generates the following code:
#Component
#Singleton
public interface ExampleApplicationComponent {
}
Also check out Google Auto if you are interested in code generation tools.
I'm not entirely sure that what I'm going to say is appropriate for an answer, but I'll take a chance here.
Even if you find a way to do what you want, don't do this in production (it is fine if you just want to learn code generation techniques).
The benefits you get from such an approach are small (not writing several lines of trivial code), but consider the drawbacks:
The logic for code generation needs to be written/debugged/maintained
Such an approach will be a violation of "principle of least astonishment"
Code generation is BAD
Note the third point - I really mean it. Usage of code generation always leads to maintenance overhead, therefore it should be used only as a last resort.
Dagger by itself uses code generation, but for a good reason - performance. However, performance is not an issue in your case.
To summarize: your idea is very interesting, but approaches like this should not be used for production applications (unless this functionality is added to Dagger natively).
I’m new to Dagger 2. I have this scenario, I wan't to inject an object across my app (in presenters, in api)
I do not have a way to provide it initially. It is not created till after authentication at some stage in my app.
From the documentation http://google.github.io/dagger/
I see Lazy loading might be a way to solve this e.g
#Inject
Lazy<Grinder> lazyGrinder;
and then get the value like this using:
lazyGrinder.get().grind();
My questions are:
Can I safely swap the object after this with a new one?
Are there any other recommended ways to do this?
Thanks
This isn't a good match for Lazy. Lazy is a great way to delay expensive object initialization, but it implies some semantics that you don't want or need, particularly regarding the "safely swap" behavior you want.
To put it simply, Lazy is a Provider wrapper that memoizes locally:
If you never call get, Dagger never creates the object in question.
The first call to get creates and stores the object instance.
The second call to get returns the same instance, and so on forever, regardless of whether the object was marked as Singleton.
This makes Lazy an excellent choice for an expensive object that would otherwise be a field (but may never be used). However, if the reference is likely to change (as your will), Lazy will simply be confusing: It will store the value at first use and never locally update, so multiple out-of-date copies might be floating around in your application regardless of what the "right" value is at any given time.
To borrow the use of Grinder from your example, better solutions include:
Using a #Provides method that returns a field in a Module, which can be updated later. You'll need to inject Provider<Grinder> for every long-lived object instance, because injected references to Grinder alone won't update. This still might be the best bet if you have a lot of short-lived objects.
The reference is implicitly singleton, but is not annotated as such, because you're controlling the instance yourself. Dagger will call your getGrinder method frequently.
#Module public class YourModule {
private Grinder grinder;
public void setGrinder(Grinder grinder) {
this.grinder = grinder;
}
#Provides public Grinder getGrinder() {
return grinder;
}
}
/* elsewhere */
YourModule module = new YourModule();
YourComponent component = DaggerYourComponent.builder()
.yourModule(module)
.build();
/* ... */
module.setGrinder(latestAndGreatestGrinder);
As EpicPandaForce mentioned in the comments, create/bind a singleton GrinderHolder, GrinderController, or AtomicReference object that provides the current instance and allows for updating. That way it's impossible to inject a Grinder directly, but easy and obvious to inject the object that fetches the current correct Grinder. If your singleton GrinderHolder implementation doesn't create the Grinder until the first time you ask for it, then you have effectively created a Lazy singleton on your own.
If you aren't able to provide the object at the time of Component creation, don't add it to your Component graph! That is asking for confusing graph dependencies and inconsistency. A better solution to what you are considering is a #Subcomponent approach, which allows you to create a new component which inherits the dependencies from the parent, but also adds new one. Here's an example:
#Component
interface RegularComponent {
#AppInstanceId String appInstanceId(); // unique per app install; not related to logging in
AuthenticatedComponent newAuthenticatedComponent();
}
#Subcomponent
interface AuthenticatedComponent {
Set<Friend> friends();
#AccountId String accountId();
}
Here, the #AccountId in the subcomponent could use the appInstanceId to provide the account ID (if it needed to) since the Subcomponent shares dependencies with its parent component.
If you need to supply state to your modules for the subcomponent (with the accountId, auth token, etc) feel free to pass it in as a parameter to the #Module and store it in a private final field. You can read more on how to supply subcomponent modules in the documentation.
One of the best advantages of using DI is it makes testing a lot easier (What is dependency injection? backs it too). Most of DI frameworks I've worked with on other programming languages (MEF on .NET, Typhoon on Obj-C/Swift, Laravel's IoC Container on PHP, and some others) allows the developer do register dependencies on a single entry point for each component, thus preventing the "creation" of dependency on the object itself.
After I read Dagger 2 documentation, it sounds great the whole "no reflection" business, but I fail to see how it makes testing easier as objects are still kind of creating their own dependencies.
For instance, in the CoffeMaker example:
public class CoffeeApp {
public static void main(String[] args) {
// THIS LINE
CoffeeShop coffeeShop = DaggerCoffeeShop.create();
coffeeShop.maker().brew();
}
}
Even though you're not explicitly calling new, you still have to create your dependency.
Now for a more detailed example, let's go to an Android Example.
If you open up DemoActivity class, you will notice the onCreate implementation goes like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Perform injection so that when this call returns all dependencies will be available for use.
((DemoApplication) getApplication()).component().inject(this);
}
You can clearly see there is no decoupling from the DI component, to the actual code. In summary, you'd need to mock/stub ((DemoApplication) getApplication()).component().inject(this); on a test case (if that's even possible).
Up to this point, I am aware Dagger 2 is pretty popular, so there is got to be something I am not seeing. So how does Dagger 2 makes testing classes easier? How would I mock, let's say a network service class that my Activity depends on? I would like the answer to be as simple as possible as I'm only interested in testing.
Dagger 2 doesn't make testing easier
...beyond encouraging you to inject dependencies in the first place, which naturally makes individual classes more testable.
The last I heard, the Dagger 2 team were still considering potential approaches to improving support for testing - though whatever discussions are going on, they don't seem to be very public.
So how do I test now?
You're correct to point out that classes which want to make explicit use of a Component have a dependency on it. So... inject that dependency! You'll have to inject the Component 'by hand', but that shouldn't be too much trouble.
The official way
Currently, the officially-recommended approach to swapping dependencies for testing is to create a test Component which extends your production one, then have that use custom modules where necessary. Something like this:
public class CoffeeApp {
public static CoffeeShop sCoffeeShop;
public static void main(String[] args) {
if (sCoffeeShop == null) {
sCoffeeShop = DaggerCoffeeShop.create();
}
coffeeShop.maker().brew();
}
}
// Then, in your test code you inject your test Component.
CoffeeApp.sCoffeeShop = DaggerTestCoffeeShop.create();
This approach works well for the things you always want to replace when you are running tests - e.g. Networking code where you want to run against a mock server instead, or IdlingResource implementations of things for running Espresso tests.
The unofficial way
Unfortunately, it the official way can involve a lot of boilerplate code - fine as a one-off, but a real pain if you only want to swap out a single dependency for one particular set of tests.
My favourite hack for this is to simply extend whichever Module has the dependency you want to replace, then override the #Provides method. Like so:
CoffeeApp.sCoffeeShop = DaggerCoffeeShop.builder()
.networkModule(new NetworkModule() {
// Do not add any #Provides or #Scope annotations here or you'll get an error from Dagger at compile time.
#Override
public RequestFactory provideRequestFactory() {
return new MockRequestFactory();
}
})
.build();
Check this gist for a full example.
"allows the developer do register dependencies on a single entry point for
each component" - analogues in Dagger 2 are the Modules and Components where you define the dependencies. The advantage is that you don't define the dependencies directly in your component thus decoupling it so later when writing unit tests you may switch the Dagger 2 component with a test one.
"it sounds great the whole "no reflection" business" - the "no reflection" thing is not the "big deal" about dagger. The "big deal" is the full dependency graph validation at compile time. Others DI frameworks don't have this feature and if you fail to define how some dependency is satisfied you will get an error late at runtime. If the error is located in some rarely used codepath your program may look like it is correct but it will fail at some point in the future.
"Even though you're not explicitly calling new, you still have to create your dependency." - well, you always have to somehow initiate dependency injection. Other DI may "hide"/automate this activity but at the end somewhere building of the graph is performed. For dagger 1&2 this is done at app start. For "normal" apps (as you shown in the example) in the main(), For android apps - in the Application class.
"You can clearly see there is no decoupling from the DI component, to the actual code" - Yes, you are 100% correct. That arises from the fact that you don't control directly the lifecycle of the activities, fragments and services in Android, i.e. the OS creates these objects for you and the OS is not aware that you are using DI. You need manually to inject your activities, fragments and services. At first this seem seems awkward but in real life the only problem is that sometimes you may forget to inject your activity in onCreate() and get NPE at runtime.