{"id":13902447,"url":"https://github.com/xmartlabs/gong","last_synced_at":"2025-12-26T22:42:06.523Z","repository":{"id":37026761,"uuid":"258843640","full_name":"xmartlabs/gong","owner":"xmartlabs","description":"Xmartlabs' Android Base Project Template","archived":false,"fork":false,"pushed_at":"2024-06-24T20:02:31.000Z","size":2262,"stargazers_count":89,"open_issues_count":9,"forks_count":5,"subscribers_count":12,"default_branch":"main","last_synced_at":"2024-08-07T22:33:46.506Z","etag":null,"topics":["android","architecture-components","baseproject","boilerplate","hacktoberfest","jetpack-compose","kotlin-android","mvi","redux-android","store"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xmartlabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-25T18:16:45.000Z","updated_at":"2024-06-18T18:27:23.000Z","dependencies_parsed_at":"2024-03-30T23:32:35.537Z","dependency_job_id":"f43954dc-a410-4ad9-921f-b5e4f6ae433b","html_url":"https://github.com/xmartlabs/gong","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2Fgong","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2Fgong/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2Fgong/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2Fgong/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmartlabs","download_url":"https://codeload.github.com/xmartlabs/gong/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226310599,"owners_count":17604610,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","architecture-components","baseproject","boilerplate","hacktoberfest","jetpack-compose","kotlin-android","mvi","redux-android","store"],"created_at":"2024-08-06T22:01:09.175Z","updated_at":"2025-12-26T22:42:06.450Z","avatar_url":"https://github.com/xmartlabs.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/images/banner.png\"\u003e\n\u003c/p\u003e\n\n[![Run lints and compile](https://github.com/xmartlabs/gong/actions/workflows/check_compile.yml/badge.svg)](https://github.com/xmartlabs/gong/actions/workflows/check_compile.yml)\n[![codebeat badge](https://codebeat.co/badges/0df37a3d-d95b-4605-bccb-98ade4232398)](https://codebeat.co/projects/github-com-xmartlabs-gong-main)\n\n**Gong** is [Xmartlabs](https://xmartlabs.com/)' official Android template project, written in Kotlin, and focused on providing a solid app architecture.\nOne of the main objectives of this project is to supply a good starting point for all new android apps, which lets you move forward fast using the latest Android Components and libraries.\nWe're using \"clean architecture\" to structure, decouple, expand, and maintain the code.\n\n## Table of content\n- [Architecture](#architecture)\n  - [Overview](#overview)\n  - [Layers components](#layers-components-and-roles)\n- [Core Libraries](#core-libraries)\n- [Setup](#setup)\n    - [Configuration and secrets](#configuration-and-secrets)\n    - [Product flavors](#product-flavors)\n- [What's next?](#whats-next)\n- [About](#about)\n\n## Architecture\nThere are 4 layers within the application:\n- Domain layer - contains high-level abstraction of the application domain (like repositories, data access) and the use cases, which contain all of the application's business logic \u0026 domain rules.\n- Data layer - implements domain layer abstractions, the `DataSources`, related to data persistence, REST calls, etc. \n- Device layer - implements domain layer abstractions that are not related to data persistence or user interface but are specific to the android platform: android services, cloud messaging, and many others.\n- Presentation (UI) layer - all the functionality related to the Android user interface: built on top of [Jetpack Compose](https://developer.android.com/jetpack/compose).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg height=\"250\" src=\"/images/arch.png\" \u003e\n\u003c/p\u003e\n\n### Overview\nIn order to understand how this work together, it's important to talk about each component's role inside the presentation layer.\n\nFirst of all, the architecture. When jetpack compose is used, it's convenient to use an architecture based on an state. In this case, a combination of MVI and Redux patterns was chosen.\nThe MVI pattern has three main components: Intent, Model, and View.\nThe intent refers to the intention to change the state of the app, so in Gong's case, it would be the actions, delivered then to ViewModel.\nViewModel holds the model component of the pattern. It is responsible of creation of a new state, which is an immutable data structure.\nAt any given moment, there is only one state in the app, which represents a single source of truth.\nThe only way to change the state is to create a new one, triggered by the actions. But when and how is the new state created?\nThe Redux pattern comes up at this point. Redux is a pattern and library for managing and updating application state, using events called \"actions\".\nMore precisely, the main components of Redux are State, Action, and Reducer.\nIn Gong the composables communicate actions to the viewModels so they can manage and emit the state back to view.\nThis ensure state can only be updated in a predictable way.\nThen, inside the model, the reducer is called with a proper action and the latest state and forward its result as an output value of the model.\nReducer is a function that takes the previous state and action and creates a new state, and in Gong this role is played by the function `processAction`, located in viewModels.\n\n\nTo continue with the insight of the project, let's see how this is done.\nWith the shared flow, actions are broadcast to an unknown number (zero or more) of subscribers.\nIn the absence of a subscriber, any posted action is immediately dropped. It is a design pattern to use for actions that must be processed immediately or not at all.\n\n\nThe ViewModel handles each action in the `processAction` method. Whenever an action is added to the \"contract\", it also has to be added here.\nSo all actions can be managed from the same place.\nWith the `channel`, each event is delivered to a single subscriber.\nAn attempt to post an event without subscribers will suspend as soon as the channel buffer becomes full, waiting for a subscriber to appear. Posted events are never dropped by default.\nThen to handle this Ui effects and all things that should be displayed only once, \"oneShotEvents\" are used. Because Channels are hot and it is not necessary to show side effect again when orientation changed or UI become visible again.\n\n\nFinally, for handling `UiState`, `StateFlow` is used.\n`StateFlow` is a state-holder observable flow that emits the current and new state updates to its collectors, similar to a `LiveData` but with an initial value.\nSo a state is always present.\nIt's also a kind of SharedFlow. It's always expected to receive last view state when UI become visible.\n\n\nGong's Workflow example:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg height=\"250\" src=\"/images/workFlow.png\" \u003e\n\u003c/p\u003e\n\n### Layers components and roles\n\nNow, as a way to give you an overview of the other layers and how the interaction with the presentation layer is done, let's review it's components.\n\nTo the presentation layer, the `UseCases` are the ones who resolve each invocation from the ViewModels, and they both interact using [coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) library.\nA `UseCase` is a reusable component that might be used from different `ViewModels`.\nThe same goes for `Repositories`, a repository can stand on its own without the ViewModel and be re-used from different use cases.\nAll these classes exist with a clear goal and purpose. The logic is split sensibly.\nIt is worth to say that these repositories refer to those of the repository pattern.\nRepository design pattern facilitates de-coupling of the business logic and the data access layers in your application with the former not having to have any knowledge on how data persistence would actually take place.\nRepositories have the function of communication between Domain Layer and Data Layer.\nMore precisely, with coroutines help, they have to implement the necessary logic so they can call Remote and Local sources methods.\n\nAt the end of the chain, as mentioned, Data Layer is found. It is responsible for persisting and obtaining all the data required for the model using different sources.\n`Repositories` use the store library to combine those different sources.\nThe remote sources are the ones who manage interaction with the different endpoints.\nThe local sources manage data base logic.\n\nThe core library for the communication between layer components is: [**Coroutines**](https://kotlinlang.org/docs/reference/coroutines-overview.html), used to perform all background tasks.\n\n## Core Libraries\nThe main libraries that we are using are:\n- [Android Architecture Components - Jetpack](https://developer.android.com/topic/libraries/architecture):\n  - [Jetpack Compose](https://developer.android.com/jetpack/compose) which is the library used by the UI with all its composables.\n  - [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel) which allows you navigate between composables while taking advantage of the Navigation component’s infrastructure and features.\n  - [Android Navigation Component](https://developer.android.com/guide/navigation) used to navigate across different pieces of content within your app.\n  - [Room](https://developer.android.com/topic/libraries/architecture/room), a SQLite object mapping library.\n- [Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) for asynchronous programming\n- [Coil](https://coil-kt.github.io/coil/), an image loading library for Android backed by Kotlin Coroutines.\n- [Koin](https://insert-koin.io/), a lightweight dependency injection framework for Kotlin.\n- [OkHttp](https://square.github.io/okhttp/) and [Retrofit](https://square.github.io/retrofit/) for network communication.\n- [Store](https://github.com/dropbox/Store), helps to manage the loading of data from different sources.\n- [AndroidSwissKnife](https://github.com/xmartlabs/AndroidSwissKnife) a set of extensions, helpers, and useful classes.\n- [Timber](https://github.com/JakeWharton/timber) one of the most popular loggers on Android.\n- [Stetho](http://facebook.github.io/stetho/), a sophisticated debug bridge for Android applications.\n- [LeakCanary](https://square.github.io/leakcanary/), a memory leak detection library for Android.\n- [AndroidSnapshotPublisher](https://github.com/xmartlabs/android-snapshot-publisher), one of the most important tools used in the QA process, it's a Gradle plugin that prepares and distributes deliverable versions easily when they are ready to test.\n\n## Setup\n\nTo use this template, you can use the [gong_setup.sh](/gong_setup.sh) script that automatizes the setup process.\nYou can run it remotely executing the following command:\n```bash\nbash \u003c(curl -s https://raw.githubusercontent.com/xmartlabs/gong/main/gong_setup.sh)\n```\n\nIt will clone and setup all variables that you need.\nIf you prefer to do it manually, you have to follow these steps:\n- Clone the project\n- Update the `applicationId` in the app's build gradle file.\n- Change the package structure based on your application id.\n\n### Configuration and secrets\nThe app's version name is defined in the project's [Gradle file](/build.gradle). \nThe app's version code is autogenerated based on the app's version name.\n\nYou have two files to define your constants:\n`config.properties` which stores all of the app's configuration, like the backend's base URL, for example.\n`secrets/keys.properties` which contains all of the secrets in your app, like a given API key for a third party service.\nThat environment's variables are injected in the app's [build.gradle](app/build.gradle), and they are accessible via the `BuildConfig` generated file.\nThe app access to that variables using the [Config](app/src/main/java/com/xmartlabs/gong/Config.kt) file.\n\nThe keystores are stored in the `secrets` folder, which is not tracked in git.\n\nThe library versions are managed in a [versions Gradle file](https://github.com/xmartlabs/GongAndroidBaseProject/blob/master/versions.gradle)\n\n### Product Flavors\n\nThe app uses two flavors, one for production (`prod`) and another for development (`dev`) build.\n\nEach flavor defines and application class (App.kt), that is used to define custom configurations in each one.\nFor example, the navigation logger listener is defined only for [development builds](app/src/dev/java/com/xmartlabs/gong/App.kt).\n\n## What's next?\nFor an answer to this question you can check the [current project status](https://github.com/xmartlabs/gong/projects/2) and if you happen to come up with a new idea you can always open a new issue!\n\n## About\nMade with ❤️ by [XMARTLABS](http://xmartlabs.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmartlabs%2Fgong","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxmartlabs%2Fgong","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmartlabs%2Fgong/lists"}