If you look at the diagram Google has published on how to architect an Android app:
https://developer.android.com/jetpack/docs/guide
you'll notice that it appears that a single repository is used abstract access to cached data and data accessed over the web. I presume that this repository is a single class and have indeed seen apps built that do have one large repository.
But this raises the question about how Dagger is used when dealing with something like a repository. In my app, I will have classes that will at times need to access cached data from local storage or using Room. Then there are REST api calls that retrieve data.
What bothers me is that if I create a single repository, I really don't want classes instantiated for the cache when the cache is not being used or instantiating classes to handle REST apis when caching is required. In other words, it seems senseless to create a component using Dagger that includes modules for local data access and web access. I want to avoid Dagger from instantiating all these classes at once and having them reside in memory while the app runs. A better solution is to only instantiate the stuff I need when I need it.
How should this be handled in Dagger? Should two separate components be used in the repository or is there some other mechanism that only creates instances of the classes I need when they are required?
Related
I am building a library that every 30 seconds displays a question (obtained from a REST Api) and allows the user to select one of the possible answers.
Also, I need to make use of that library in an app, displaying a video underneath the question.
Desired result
All the business and UI logic should be handled in the library.
Does it make sense to use an MVVM approach, with repository pattern in the library?
With this package structure?
Possible package structure
You're creating the library, which is totally different context and way of creating the codebase comparing to the app.
First of all you need to make decisions about the dependencies. Of course it is super easy to put retrofit, mvvm and other dependencies into the app and manage them further.
With library it's not that easy. What I would expect from library in the first place is to have as little dependencies as possible. If you're going to provide aar file, then the developer would have to include those dependencies in the project. On the other hand, if you're publishing the library to maven repo, the gradle will take care of the library's dependencies. However the biggest challenge here is maintaining the library and resolving conflicts in actual app that uses the library. It can lead to frustration and eventually someone can throw your library away, which is the worst thing from library creator's perspective.
What I would suggest for this small library (calling api and providing data to custom view) is to:
Use only OkHttp without retrofit to provide the data from the REST api.
If it's the case for the library, create some abstraction over the OkHttp client with public functions/methods so the developers can get the data by themselves. Cool approach for creating this kind of interface is to use Fluent Interface (for example if you want the client of the library to put their access token/secret key for the REST api to detect who is calling the api, how much, limit their requests etc)
If you want to also provide the Custom View I would suggest to think twice about separating the REST client and Custom View itself and let the developer put the data by themselves. On the other hand if you want to handle it by yourself, you have to consider error handling, state management, lifecycle callbacks for cancelling the requests etc. You can provide some Listener interfaces for the developers so they know what is going on in the custom view.
The way you structure the library is up to you, if you have only one dependency (the rest client) just pass the objects via constructor so you won't need to add another dependency. Or just simply use ServiceLocator pattern, however it should also be connected to the Application/Activity itself when setting up the library so the objects are destroyed properly
I'm exploring the new Android Architecture Components and looking to implement it into an Android app. I am firmillair with MVVM as I use the paradigm on iOS development. Having read through the Android Architecture Components guide, provided by Google: https://developer.android.com/topic/libraries/architecture/guide.html
I have just a few questions...
In the above mentioned guide, Google use the UserRepository class that access these web service API - they go on to make this class a Singleton which is probably fine, if there were only ever one screen on the app that needed data from a REST API.
My concern, is this; it seems Google advocate the need to create a repository class on a per-ViewModel basis. This sounds very wrong to me, in having so many Singlton classes in the app. If we were to have 10 screens, with ten ViewModels - each needing its own Repository module - we then have ten singletons in our app. From an iOS dev perspective, this is wrong to have so many.
The solution to this, would be to have one mediator (Repository) class, that has public methods, exposing the API to get data from a REST API. The Web service part, would be in its own class. That way, we have a decent separation of concerns.
Is it best practice, to have one repository class, per, ViewModel - or to have one per app? I'm not 100% sure on this.
Lastly, I have the same concern when it comes to Room- is Google saying we create a DB on a per ViewModel bases or just one DB per app?
I don't think the architecture guide suggests to create a separate repository class for each ViewModel. In the example that is shown Google uses a library called Dagger to inject the singleton repository class into the ViewModel. It is normally best practice to split repositories (or managers) on functionality. UserRepository is responsible for all user related api calls for example.
If you turn this repository into a singleton that you can inject in any ViewModel, any ViewModel now has access to that specific repository.
After quickly looking into Room I found this little snippet (link):
Note: You should follow the singleton design pattern when instantiating an AppDatabase object, as each RoomDatabase instance is fairly expensive, and you rarely need access to multiple instances.
This to me means that you can implement the RoomDatabase much in the same way you can use your repository classes. Simply inject them as a singleton into your ViewModel so you don't need to have multiple instances of the same database.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
How to use Dagger in my Android project and what is the main purpose of using it? I searched it on google but I am not clear about it.So please give me the best solution and an example also if possible.
Many Android apps rely on instantiating objects that often require other dependencies. For instance, a Twitter API client may be built using a networking library such as Retrofit. To use this library, you might also need to add parsing libraries such as Gson. In addition, classes that implement authentication or caching may require accessing shared preferences or other common storage, requiring instantiating them first and creating an inherent dependency chain.
Dagger 2 analyzes these dependencies for you and generates code to help wire them together. While there are other Java dependency injection frameworks, many of them suffered limitations in relying on XML, required validating dependency issues at run-time, or incurred performance penalties during startup. Dagger 2 relies purely on using Java annotation processors and compile-time checks to analyze and verify dependencies. It is considered to be one of the most efficient dependency injection frameworks built to date.
Advantages
Here is a list of other advantages of using Dagger 2:
Simplifies access to shared instances. Just as the ButterKnife library makes it easier to define references to Views, event handlers, and resources, Dagger 2 provides a simple way to obtain references to shared instances. For instance, once we declare in Dagger our singleton instances such as MyTwitterApiClient or SharedPreferences, we can declare fields with a simple #Inject annotation:
public class MainActivity extends Activity {
#Inject MyTwitterApiClient mTwitterApiClient;
#Inject SharedPreferences sharedPreferences;
public void onCreate(Bundle savedInstance) {
// assign singleton instances to fields
InjectorClass.inject(this);
}
}
Easy configuration of complex dependencies. There is an implicit order in which your objects are often created. Dagger 2 walks through the dependency graph and generates code that is both easy to understand and trace, while also saving you from writing a large amount of boilerplate code you would normally need to write by hand to obtain references and pass them to other objects as dependencies. It also helps simplify refactoring, since you can focus on what modules to build rather than focusing on the order in which they need to be created.
Easier unit and integration testing Because the dependency graph is created for us, we can easily swap out modules that make network responses and mock out this behavior.
Scoped instances Not only can you easily manage instances that can last the entire application lifecycle, you can also leverage Dagger 2 to define instances with shorter lifetimes (i.e. bound to a user session, activity lifecycle, etc.).
Android lets us extend Application, which is a great place to store our singletons so they can be easily reused throughout different pages (actiivities) in the app.
What is Google App-Engine's equivalent of this?
I am using dagger, and I don't want to create a new object graph for every endpoint.
One option (although I'm by no means sure it's the best) is just to self-inject your Cloud Endpoints class (through static field injection).
Presumably you're initialising the object graph in a ServletContextListener so you could do so there, before your endpoint methods are called.
Dagger 1.x supports staticInjections on the module annotation (to do that for you) but this is apparently no longer supported in 2.x.
I am developing an Android application using eclipse which has totally 29 classes in a package called com.companyname.appname.This 29 classes includes Activities,List Fragments,Loaders,Service, DbHelper,Jsonparser,Adapter and NetworkConnection classes.
I plan to separate packages like below,
Method 1:
com.companyname.appname.activities (includes all activity class of application)
com.companyname.appname.services (includes all service class of application)
com.companyname.appname.loaders (includes all loader class of application)
com.companyname.appname.fragments (includes all fragment class of application)
com.companyname.appname.database (includes all database helper class of application)
com.companyname.appname.utilities (includes other utility classes(Jsonparser,Netwrok connection detection,SimpleCursorAdapter) of application)
Method 2:
Separate each package for each Activity(it includes the associated fragments,loaders,utilities,services,etc)
Which is the efficient method? Or I need to separate packages in different method efficiently?
What are all the best practices of package separation in android code design?
To a great extent, it's a matter of taste. As to some criteria , like with other kinds of encapsulation, the following can be applied :
Loose coupling
Tight cohesion
In other words, avoid unnecessary dependencies among unrelated parts and group together what belongs together.
Think of your packages potentially reused in another application or another type of build: phone/tablet, Google / Amazon. Or, contrary, ones too specific to a particular case to be ever reused.
That or other kind of reasoning will help you structure your code based on some needs rather than an arbitrary choice.
Edit: An anecdotal analogy. Recommendations on arranging files into folders, AFAIK, from Microsoft once explaining their "object oriented" UX. One way: have folders like Word Documents, Excel Spreadsheets, etc. And the other like Business, Entertainment, etc. Same approach applies to any packaging.
packages purpose is just for organization. The first method will allow you without thinking too much to place new classes and find them easily.
The second method will be harder sometime, because some classes can be classified in several packages.