Welcome
It is written 100% in Kotlin with both UI and Unit tests - we will also be keeping this up-to-date as libraries change!
Note: The use of clean architecture may seem over-complicated for this sample project. However, this allows us to keep the amount of boilerplate code to a minimum and also demonstrate the approach in a simpler form.
Clean Architecture will not be appropriate for every project, so it is down to you to decide whether or not it fits your needs
The architecture of the project follows the principles of Clean Architecture. Here's how the sample project implements it:
The sample app when run will show you a simple list of all the Bufferoos (Buffer team members!).
Let's look at each of the architecture layers and the role each one plays :)
This layer makes use of the Android Framework and is used to create all of our UI components to display inside of the Browse Activity. The layer receives its data from the Presentation layer and when retrieved, the received models are mapped using the Bufferoo Mapper so that the model can be mapped to this layer's interpretation of the Bufferoo instance, which is the BufferooViewModel. The Activity makes use of the BrowseContract to enable communication to and from the presenter.
This layer's responsibility is to handle the presentation of the User Interface, but at the same time knows nothing about the user interface itself. This layer has no dependence on the Android Framework, it is a pure Kotlin module. Each Presenter class that is created implements the Presenter interface defined within an instance of a contract - in this case the BrowseContract, which also contains an interface for the View interface.
When a Presenter is constructed, an instance of this View is passed in. This view is then used and the presenter is set for it using the implemented setPresenter() call.
The presenters use an instance of a SingleUseCase from the Domain layer to retrieve data. Note here that there is no direct name reference to the UseCase that we are using - we do inject an instance of the GetBufferoos UseCase, however.
The presenter receives data from the Domain layer in the form of a Bufferoo. These instances are mapped to instance of this layers model, which is a BufferooView using the BufferooMapper.
The domain layer responsibility is to simply contain the UseCase instance used to retrieve data from the Data layer and pass it onto the Presentation layer. In our case, we define a GetBufferoos - this use case handles the subscribing and observing of our request for data from the BufferooRepository interface. This UseCase extends the SingleUseCase base class - therefore we can reference it from outer layers and avoid a direct reference to a specific implementation.
The layer defines the Bufferoo class but no mapper. This is because the Domain layer is our central layer, it knows nothing of the layers outside of it so has no need to map data to any other type of model.
The Domain layer defines the BufferooRepository interface which provides a set of methods for an external layer to implement as the UseCase classes use the interface when requesting data.
The Data layer is our access point to external data layers and is used to fetch data from multiple sources (the cache and network in our case). It contains an implementation of the BufferooRepository, which is the BufferooDataRepository. To begin with, this class uses the BufferooDataStoreFactory to decide which data store class will be used when fetching data - this will be either the BufferooRemoteDataStore or the BufferooCacheDataStore - both of these classes implement the BufferooDataStore repository so that our DataStore classes are enforced.
Each of these DataStore classes also references a corresponding BufferooCache and BufferooRemote interface, which is used when requesting data from an external data source module.
This layers data model is the BufferooEntity. Here the BufferooMapper is used to map data to and from a Bufferoo instance from the domain layer and BufferooEntity instance from this layer as required.
The Remote layer handles all communications with remote sources, in our case it makes a simple API call using a Retrofit interface. The BufferooRemoteImpl class implements the BufferooRemote interface from the Data layer and uses the BufferooService to retrieve data from the API.
The API returns us instances of a BufferooModel and these are mapped to BufferooEntity instance from the Data layer using the BufferooEntityMapper class.
The Cache layer handles all communication with the local database which is used to cache data.
The data model for this layer is the CachedBufferoo and this is mapped to and from a BufferooEntity instance from the Data layer using the BufferooEntityMapper class.
We will be happy to answer any questions that you may have on this approach, and if you want to lend a hand with the boilerplate then please feel free to submit an issue and/or pull request
Again to note, use Clean Architecture where appropriate. This is example can appear as over-architectured for what it is - but it is an example only. The same can be said for individual models for each layer, this decision is down to you. In this example, the data used for every model is exactly the same, so some may argue that "hey, maybe we don't need to map between the presentation and user-interface layer". Or maybe you don't want to modularise your data layer into data/remote/cache and want to just have it in a single 'data' module. That decision is down to you and the project that you are working on ����
A special thanks to the authors involved with these two repositories, they were a great resource during our learning!
Best practices in Android development Lessons learned from Android developers in Futurice. Avoid reinventing the wheel by following these guidelines. If you are interested in iOS or Windows Phone deve
Clean Architecture on Android: the Teamwork.com way! The purpose of this repository is to showcase, with a very simple (but hopefully clear) sample Android project, how we implement Uncle Bob's Clean
This repository holds 2 projects: Sample Giphy App is a test Project that displays paginated trending GIFs from Giphy and also contains search functionality. This small project is a good starting poin
Getting Started If you don't have Docker, download it from the address below. https://www.docker.com/products/docker-desktop Download this repository Open onion-architecture.sln with Visual studio Con
Android Components Architecture in a Modular Word Android Components Architecture in a Modular Word is a sample project that presents modern, 2020 approach to Android application development using Kot
Android MVVM Architecture: Sample App UPDATE: Check this for updated project This repository contains a detailed sample app that implements MVVM architecture using Dagger2, Room, RxJava, FastAndroidNe
Android 架构文章合集 携程 携程Mobile架构演化(视频) 携程Android App插件化和动态加载实践 阿里 陶钧谈淘宝客户端应用框架实践 QCon旧金山演讲总结:阿里无线技术架构演进 手机淘宝构架演化实践 手机淘宝Android客户端架构 漫谈移动应用架构设计 大规模团队的Android开发 支付宝钱包客户端技术架构 百度 手机百度Android平台平台化解决方案 腾讯 涅盘新生—