[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7342":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":21,"defaultBranch":22,"hasWiki":20,"hasPages":21,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":16,"starSnapshotCount":16,"syncStatus":35,"lastSyncTime":36,"discoverSource":37},7342,"android-clean-architecture-boilerplate","bufferapp\u002Fandroid-clean-architecture-boilerplate","bufferapp","An android boilerplate project using clean architecture","",null,"Kotlin",3684,512,143,25,0,3,30.13,"MIT License",true,false,"main",[24,25,26,27,28,29,30,31],"android","android-application","android-architecture","android-boilerplate","android-development","boilerplate","buffer","clean-architecture","2026-06-12 02:01:38","[![Build Status](https:\u002F\u002Ftravis-ci.org\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate.svg?branch=master)](https:\u002F\u002Ftravis-ci.org\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate) [![codecov](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fbranch\u002Fmaster\u002Fgraph\u002Fbadge.svg)](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate) [![Codacy Badge](https:\u002F\u002Fapi.codacy.com\u002Fproject\u002Fbadge\u002FGrade\u002F278fa00f492d48a288ab64188d15fb61)](https:\u002F\u002Fwww.codacy.com\u002Fapp\u002Fhitherejoe\u002Fandroid-clean-architecture-boilerplate?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=bufferapp\u002Fandroid-clean-architecture-boilerplate&amp;utm_campaign=Badge_Grade) \n\n# Android Clean Architecture Boilerplate\n\nWelcome 👋 We hope this boilerplate is not only helpful to other developers, but also that it helps to educate in the area of architecture. We created this boilerplate for a few reasons:\n\n1. To experiment with modularisation\n2. To share some approaches to clean architecture, especially as we've been [talking a lot about it](https:\u002F\u002Facademy.realm.io\u002Fposts\u002Fconverting-an-app-to-use-clean-architecture\u002F)\n3. To use as a starting point in future projects where clean architecture feels appropriate\n\nIt is written 100% in Kotlin with both UI and Unit tests - we will also be keeping this up-to-date as libraries change!\n\n### Disclaimer\n\nNote: 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.\n\nClean Architecture will not be appropriate for every project, so it is down to you to decide whether or not it fits your needs 🙂\n\n## Languages, libraries and tools used\n\n* [Kotlin](https:\u002F\u002Fkotlinlang.org\u002F)\n* Android Support Libraries\n* [RxJava2](https:\u002F\u002Fgithub.com\u002FReactiveX\u002FRxJava\u002Fwiki\u002FWhat's-different-in-2.0)\n* [Dagger 2 (2.11)](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fdagger)\n* [Glide](https:\u002F\u002Fgithub.com\u002Fbumptech\u002Fglide)\n* [Retrofit](http:\u002F\u002Fsquare.github.io\u002Fretrofit\u002F)\n* [OkHttp](http:\u002F\u002Fsquare.github.io\u002Fokhttp\u002F)\n* [Gson](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgson)\n* [Timber](https:\u002F\u002Fgithub.com\u002FJakeWharton\u002Ftimber)\n* [Mockito](http:\u002F\u002Fsite.mockito.org\u002F)\n* [Espresso](https:\u002F\u002Fdeveloper.android.com\u002Ftraining\u002Ftesting\u002Fespresso\u002Findex.html)\n* [Robolectric](http:\u002F\u002Frobolectric.org\u002F)\n\n## Requirements\n\n* JDK 1.8\n* [Android SDK](https:\u002F\u002Fdeveloper.android.com\u002Fstudio\u002Findex.html)\n* Android O ([API 26](https:\u002F\u002Fdeveloper.android.com\u002Fpreview\u002Fapi-overview.html))\n* Latest Android SDK Tools and build tools.\n\n## Architecture\n\nThe architecture of the project follows the principles of Clean Architecture. Here's how the sample project implements it:\n\n![architecture](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fart\u002Farchitecture.png?raw=true)\n\nThe sample app when run will show you a simple list of all the Bufferoos (Buffer team members!).\n\u003Cp align=\"center\">\n\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fart\u002Fdevice_screenshot.png\" alt=\"Drawing\" style=\"width: 10px;\"\u002F>\n\u003C\u002Fp>\n\nLet's look at each of the architecture layers and the role each one plays :)\n\n![architecture](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fart\u002Fui.png?raw=true)\n\n### User Interface\n\nThis layer makes use of the Android Framework and is used to create all of our UI components to display inside of the [Browse Activity](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002F9a1308c42c0c882fc724a0e579ee1ce4d454f961\u002Fmobile-ui\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fui\u002Fbrowse\u002FBrowseActivity.kt). The layer receives its data from the Presentation layer and when retrieved, the received models are mapped using the [Bufferoo Mapper](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002F9a1308c42c0c882fc724a0e579ee1ce4d454f961\u002Fmobile-ui\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fui\u002Fmapper\u002FBufferooMapper.kt) so that the model can be mapped to this layer's interpretation of the Bufferoo instance, which is the [BufferooViewModel](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002F9a1308c42c0c882fc724a0e579ee1ce4d454f961\u002Fmobile-ui\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fui\u002Fmodel\u002FBufferooViewModel.kt). The Activity makes use of the [BrowseContract](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002Fbrowse\u002FBrowseBufferoosContract.kt) to enable communication to and from the presenter.\n\n### Presentation\n\nThis 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](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002FBasePresenter.kt) interface defined within an instance of a contract - in this case the [BrowseContract](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002Fbrowse\u002FBrowseBufferoosContract.kt), which also contains an interface for the [View](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002FBaseView.kt) interface.\n\nWhen 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()](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002Fbrowse\u002FBrowseBufferoosPresenter.kt#L15) call.\n\nThe presenters use an instance of a [SingleUseCase](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdomain\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdomain\u002Finteractor\u002FSingleUseCase.kt) 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](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdomain\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdomain\u002Finteractor\u002Fbrowse\u002FGetBufferoos.kt) UseCase, however.\n\nThe presenter receives data from the Domain layer in the form of a [Bufferoo](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002Fmodel\u002FBufferooView.kt). These instances are mapped to instance of this layers model, which is a BufferooView using the [BufferooMapper](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fpresentation\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fpresentation\u002Fmapper\u002FBufferooMapper.kt).\n\n### Domain\n\nThe 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](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdomain\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdomain\u002Finteractor\u002Fbrowse\u002FGetBufferoos.kt) - this use case handles the subscribing and observing of our request for data from the BufferooRepository interface. This UseCase extends the [SingleUseCase](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdomain\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdomain\u002Finteractor\u002FSingleUseCase.kt) base class - therefore we can reference it from outer layers and avoid a direct reference to a specific implementation.\n\nThe layer defines the [Bufferoo](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Ftree\u002Fmaster\u002Fdomain\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdomain\u002Fmodel) 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.\n\nThe Domain layer defines the [BufferooRepository](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdomain\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdomain\u002Frepository\u002FBufferooRepository.kt) interface which provides a set of methods for an external layer to implement as the UseCase classes use the interface when requesting data.\n\n![architecture](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fart\u002Fdata.png?raw=true)\n\n### Data\n\nThe 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](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002FBufferooDataRepository.kt). To begin with, this class uses the [BufferooDataStoreFactory](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Fsource\u002FBufferooDataStoreFactory.kt) to decide which data store class will be used when fetching data - this will be either the [BufferooRemoteDataStore](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Fsource\u002FBufferooRemoteDataStore.kt) or the [BufferooCacheDataStore](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Fsource\u002FBufferooCacheDataStore.kt) - both of these classes implement the [BufferooDataStore](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Frepository\u002FBufferooDataStore.kt) repository so that our DataStore classes are enforced.\n\nEach of these DataStore classes also references a corresponding [BufferooCache](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Frepository\u002FBufferooCache.kt) and [BufferooRemote](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Frepository\u002FBufferooRemote.kt) interface, which is used when requesting data from an external data source module.\n\nThis layers data model is the [BufferooEntity](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Ftree\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Fmodel). Here the [BufferooMapper](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Fmapper\u002FBufferooMapper.kt) is used to map data to and from a Bufferoo instance from the domain layer and BufferooEntity instance from this layer as required.\n\n### Remote\n\nThe Remote layer handles all communications with remote sources, in our case it makes a simple API call using a Retrofit interface. The [BufferooRemoteImpl](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fremote\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fremote\u002FBufferooRemoteImpl.kt) class implements the [BufferooRemote](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fdata\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fdata\u002Frepository\u002FBufferooRemote.kt) interface from the Data layer and uses the [BufferooService](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fremote\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fremote\u002FBufferooService.kt) to retrieve data from the API.\n\nThe API returns us instances of a [BufferooModel](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fremote\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fremote\u002Fmodel\u002FBufferooModel.kt) and these are mapped to BufferooEntity instance from the Data layer using the [BufferooEntityMapper](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fremote\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fremote\u002Fmapper\u002FBufferooEntityMapper.kt) class.\n\n### Cache\n\nThe Cache layer handles all communication with the local database which is used to cache data. \n\nThe data model for this layer is the [CachedBufferoo](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fcache\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fcache\u002Fmodel\u002FCachedBufferoo.kt) and this is mapped  to and from a BufferooEntity instance from the Data layer using the [BufferooEntityMapper](https:\u002F\u002Fgithub.com\u002Fbufferapp\u002Fandroid-clean-architecture-boilerplate\u002Fblob\u002Fmaster\u002Fcache\u002Fsrc\u002Fmain\u002Fjava\u002Forg\u002Fbuffer\u002Fandroid\u002Fboilerplate\u002Fcache\u002Fmapper\u002FBufferooEntityMapper.kt) class.\n\n## Conclusion\n\nWe 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\u002For pull request 🙂\n\nAgain 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\u002Fremote\u002Fcache 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 🙌🏻\n\n## Thanks\n\nA special thanks to the authors involved with these two repositories, they were a great resource during our learning!\n\n- https:\u002F\u002Fgithub.com\u002Fandroid10\u002FAndroid-CleanArchitecture\n\n- https:\u002F\u002Fgithub.com\u002Fgooglesamples\u002Fandroid-architecture\n","这是一个使用Clean Architecture模式构建的Android样板项目，旨在提供一个模块化且易于维护的应用程序结构。项目完全采用Kotlin编写，并集成了RxJava2、Dagger 2等现代Android开发库和技术，支持UI和单元测试。通过实现清晰分离的数据访问层、业务逻辑层与展示层，该项目为开发者展示了如何有效地组织代码以提高可读性和可测试性。特别适合于需要遵循良好架构原则的新Android应用开发场景或作为学习Clean Architecture模式的参考示例。",2,"2026-06-11 03:11:51","top_language"]