Bug P3
Status Update
Comments
l....@gmail.com <l....@gmail.com> #2
Forgot to note the environment.
This crash occurs on only API 21.
This crash occurs on only API 21.
cc...@google.com <cc...@google.com> #3
This crash occurs on API 22 and 23 when the user doesn't have Google Play installed. Related discussions: https://stackoverflow.com/q/41025200/842697
Description
When developing apps, I strive to have as much Kotlin-only modules (with no `android-application` or `android-library` plugins applied) as possible. Non-android modules are much faster -- I appreciate all the performance improvements, but when at scale, differences still add up. Android modules also leak Android dependencies, so when implementing clean architecture, they leave room to accidentally use Android classes where they shouldn't be available. Having no possibility to add flavors encourages dependency injection, etc. Overall when the application grows, the more Android-free modules the better. When using the Architecture Components though, there are some things which would be useful to have in such Kotlin-only modules, but which can't be imported, because much of the components libraries are provided as `aar`s.
One example is LiveData. Neither lifecycle-livedata nor lifecycle-livedata-core contain Android framework dependencies. The Seems like the only transitive dependency of livedata artifacts that actually uses Android framework classes is `core-runtime`. But even then `TaskExecutor` and `ArchTaskExecutor` _don't_ require Android framework. It would make sense to take this one step further and have only `DefaultTaskExecutor` in an android library, and e.g. move executor abstraction to `core-common` artifact. This would be particularly useful because it would allow LiveData to be passed from a module in data layer (one that implements Room database for example) through the domain (which should be Android-free) to presentation layer. Right now folks that want to keep the architecture clean need to convert stuff to reactive streams instead.
Similarly, `view-model` artifact. I'd be extatic to be able to create presentation module that has access to ViewModel, but not Android classes. This would help in keeping the architecture clean and modularising better. Combining that with LiveData being accessible, entire presentation can be kept in a Kotlin-only module. That's not possible right now, because of two classes in the same artifact -- `AndroidViewModel` and `ViewModelProvider`. `ViewModelProvider` doesn't even use Android class by itself, only its inner class `AndroidViewModelFactory`. `AndroidViewModelProvider` is more of a runtime dependency, and in my opinion using `AndroidViewModel` should be an explicit opt-in.
Final example (I haven't analyzed every library) is paging. It starts off well: `paging-common` contains most of the paging-related classes and it's provided as a `jar`. However, to be able to use that in the domain, it would still make most sense to expose `LiveData<PagedList>` directly. This is impossible, because LivePagedListBuilder lives in an `aar`, and that's only because the same artifact contains a `PagedListAdapter`. With `RxPagedListBuilder` it's even more straightforward, since the class obviously doesn't need anything more than `ArchTaskExecutor`, which we've already seen could be provided in a jar.
I understand that this would create more modules to manage, but I feel this is worth it, since it actually helps using Architecture Components within clean architecture, with clear boundaries between the layers. If the concern is that in the future some of these presently Android-free classes/artifacts will contain Android dependencies, then I'd urge you to reconsider. The abstractions that are in place right now work well, and in any case proper architecture actually forces new abstractions if necessary, instead of enabling the "easy" solutions, which I feel adding Android dependency is.
Also it really does look like what I ask for was at least considered, based on the abstractions that are there. It's just how they are grouped in packages that makes the components less flexible.