In Clean Architecture, a Repository contains Remote (Retrofit) and Local (Room) data source. I see Remote is pure Kotlin module. However because Room need to access Android Context, thus Local is Android module.
So, must Repository is Android module because of Local module? And if yes, do you know any abstraction to avoid Context in Local module and make that module becomes pure Kotlin?
The distinction isn't between programming language. The deciding factor is whether it relies on any components from Android, such as Context, to operate.
I have a module written in kotlin that is a java-library. This library contains my "domain" logic and does not contain any Android components.
In your case, because you're using Room, yes this module will need to be a com.android.library module.
I don't think there is a way round this. You could split your module into two obviously: one for Retrofit (data-api) and one for Room (data-local)
Here's link
It's good to see the open source on the link above.
Related
I'm almost finishing migrating my app to MVVM with databinding and livedata (still java though) and now I have much more than a decent architectured Android app (which I'm showing below). I'm happy with that, but would like to go one step further.
Talking about clean architecture, I'm trying to figure out how to do a proper separation of concerns in Android (database, business, services, etc).
I work in .net and in that platform, what you do to separate layers is to create a different proyect for each layer (database, bussiness, presentation) and then you reference them in the correct order, but projects are mostly independent one of the others.
In Android, and as far as I know, you have an app module and even though I have a nice package agrupation, all is "together" into the same project.
I'm not sure if this is the best approach to really follow clean architecture principles. I've heard about Dagger, heard you can create modules with it, but not sure if it is intended for what I'm trying to do.
Any help/hints about a good way to implement separation of concerns in Android?
My current app structure:
com
xxx
xxx
dto
class_1_dto.java
...
class_N_dto.java
helpers
helper_http.java
helper_json.java
helper_utils.java
helper_enum.java
helper_file.java
helper_smtp.java
helper_date.java
...
model
model_class_1
model_class_2
...
all_model_classes_linked_to_AWS_database
poco
some_poco_classes
repository
aws
IAWSDAO
AWS_Repository
...
all_stuff_related_to_AWS_database_query
local
model_class_1_repo
model_class_2_repo
...
all_stuff_related_to_SQLite_database_query
services
model_class_1_serv
model_class_2_serv
...
all_stuff_related_to_local_repos_query
ui
activities
activity_1
activity_1_viewmodel
activity_2
activity_2_viewmodel
...
activity_N
activity_N_viewmodel
component
custom_view_1
custom_view_2
...
helpers
view_helper_1
...
view_helper_N
assets
res
...
You can segregate your concerns like (app, core, network, service, repository) by making multiple modules. Just like 'app' is a module, you can create an independent module for each concern and you can use Koin for dependency injection between the modules.
For reference here is an example github repo:
https://github.com/Fahad-github/Bykea-CaseStudy-MusicApp
I'm very familiar with MVVM architectural pattern in android. To take it much further, I'm doing my next project by following clean code principles (SOLID). I have separated the entire app in three modules. 1) App (presentation + framework) 2) Data 3) Domain. My doubt is that whether I can keep library dependencies (i.e. Firebase) in Data module or not. Right now, I'm using interface to access app related stuffs like shared preferences, location fetchers, retrofit, etc.
I need to expect values like AuthResult from Data module. For that I need to add Firebase dependencies in the data module's Gradle file. I think that will violate the Higher level module should not depend on lower lever module rule.
Can anyone clarify this for me?
After going through several articles on MVVM + Clean Code, I came to a conclusion that I cannot be using any dependencies related to android framework inside either domain or data module. Otherwise it will be violating the Dependency Inversion principle of SOLID.
Dependency Inversion principle
Higher level module should not be dependent on Lower level modules, and both should be dependent on abstraction.
In English -> You cannot directly access framework related components like database, gps, retrofit, etcetera from data or domain layers. They should not care about those stuffs. They should be totally independent of android related components. We can use interface to satisfy the rule of abstraction.
Therefore, my data module and domain module contains only language dependencies. Whatever android-framework-related data I want, I acquire it by implementing interfaces.
In Android, I'm using clean architecture and putting my code packaged by layer. So I've 4 layers (modules) :
app
data
device
domain
I know, correct me if I'm wrong, that acceptance testing (Using FitNesse) should replace UI in better words, it should mimic UI and test core functions of the system from customer's point of view.
My Question is :
Should I create another module for FitNesse fixtures and stuff, with dependencies on each module in the system?
This is what I usually see done, yes. The builder system (maven, gradle, etc.) is tweaked so that it does not include the module containing the fixtures in the production artifact. The module containing the fitnesse fixtures is aware of / has dependencies to all of the modules it directly tests, which tends to be the domain layer.
I'm using working on a project in the CLEAN architecture where the project is broken into the "Presentation", "Domain" and "Data" modules, where the Domain module hosts the "Entities" that are basically the data models specific to this project. An example of this architecture is here.
Unlike the other two module, "Domain" is a pure Java library module, which is great for clarity and testing as it doesn't have the Android overhead, however it also means I'm now not able to use libraries like "Parceler" to which is very Android specific. Is there a way around this?
Parceler allows you to configure beans outside of the given module to generate a wrapping Parcelable via the #ParcelClass annotation. This means you can configure the given bean as a #Parcel outside of the Data layer, and in the presentation layer (or wherever else you want). See http://parceler.org/#classes_without_java_source for specifics.
The org.parceler:parceler-api module is also pure Java, it has no dependencies on the Android api. Therefore you should be free to annotate your Data module without violating the CLEAN archetecture you're seeking. The annotation compiler portion (org.parceler:parceler) of the library, however, does rely on the Android API, so you'll need to run it in the android-specific module. This leaves you with the follow:
Include the parceler-api library in your Data module and annotate your Data layer beans (#Transient, #ParcelProperty, etc). If you don't need any specific configuration, you can avoid including the parceler-api as a dependency.
Add the parceler and parceler-api libraries to your Android-specific module (Presentation?).
Add a #ParcelClass annotation with each class from your data module you want to be an #Parcel to an arbitrary class (Application?). This will direct Parceler to generate a Parcelable for each class identified within the #ParcelClass parameter.
Aloha -
I'm migrating code from an existing web application into an Android application. The existing web app uses Spring extensively for dependency injection.
I'd like to reuse the Spring dependency injection if I can, but I do not see a way to initialize it like you would in a webapp:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
Google does not turn up much help on the subject, other than use Guice. I'd rather not do that as the web app is still being developed, so if I were to use Guice for dependencies, I would constantly need to sync up between the Spring dependencies and Guice.
Is there any way to use Spring for DI on Android in a plug and play fashion, or do I have to look at rewriting all this stuff in another way?
Thanks!
Do not try to use spring dependency injection in your android app. Android and spring do not mix together in any way,shape, or form. Instead, use the factory design pattern to generate objects.
Have you looked at rolling your on ApplicationContext, perhaps extending FileSystemXmlApplicationContext and overriding getResourceByPath(String path) to pull your context files from the assets/ folder?
If you decide to go down the Guice route, RoboGuice is a nice little library: http://code.google.com/p/roboguice/
Please DO use Spring dependency injection in your android app! :-)
However you won't be able to use the original Spring Framework, as it requires the java.beans package, that is not present on Android.
If your existing Spring configuration is not too extraordinary, you will be happy with my port of the Spring Framework called RoboSpring. From its description:
RoboSpring is a (real) port of the Spring Framework to the Android platform. Additionally it offers preliminary support for functionality introduced by RoboGuice like injecting View references into Activities and more. RoboSpring is based on version 3.1.0 RELEASE of Spring's core, beans, context and aop components. It offers the following functionality:
Configure application components with a Spring configuration file
(XML)
Autowire your Android components with beans from the Spring application context.
Inject the Android application context into your Spring Beans.
Inject views into Activities.
… and more
Please see here: https://github.com/dthommes/RoboSpring