{"id":17335680,"url":"https://github.com/aartikov/replica","last_synced_at":"2025-04-14T12:52:44.691Z","repository":{"id":43741487,"uuid":"438253231","full_name":"aartikov/Replica","owner":"aartikov","description":"Replica is a KMM library for organizing of network communication in a declarative way.","archived":false,"fork":false,"pushed_at":"2025-04-11T10:33:31.000Z","size":3206,"stargazers_count":33,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-11T12:03:28.842Z","etag":null,"topics":["android","android-library","architecture","caching","ios","ios-library","kmm-library","kotlin","networking","state-management","ux"],"latest_commit_sha":null,"homepage":"https://aartikov.github.io/Replica/","language":"HTML","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/aartikov.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":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-12-14T12:57:24.000Z","updated_at":"2025-04-04T08:25:45.000Z","dependencies_parsed_at":"2023-02-14T17:01:33.461Z","dependency_job_id":"2db43c92-ef55-4e7d-9979-062fbcf17553","html_url":"https://github.com/aartikov/Replica","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aartikov%2FReplica","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aartikov%2FReplica/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aartikov%2FReplica/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aartikov%2FReplica/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aartikov","download_url":"https://codeload.github.com/aartikov/Replica/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248885342,"owners_count":21177623,"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","android-library","architecture","caching","ios","ios-library","kmm-library","kotlin","networking","state-management","ux"],"created_at":"2024-10-15T15:11:48.870Z","updated_at":"2025-04-14T12:52:44.680Z","avatar_url":"https://github.com/aartikov.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.aartikov/replica-core)](https://repo1.maven.org/maven2/com/github/aartikov/replica-core/)\n[![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)\n[![Documentation](https://img.shields.io/badge/docs-Documentation-informational)](https://aartikov.github.io/Replica/)\n\n\u003ch1 align=\"center\"\u003eReplica\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n  KMM library for organizing of network communication in a declarative way.\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cstrong\u003eDeveloped in \u003ca href=\"https://mobileup.ru/\"\u003eMobileUp\u003c/a\u003e company.\u003c/strong\u003e\n\u003c/div\u003e\n\n## Motivation\nWhile libraries such as *Retrofit* and *Kotlin Serialization* help to make network requests, Replica takes on another challenges.\n\nIt is important to keep data up to date on a client. But we shouldn't call network requests too frequently to not waste server resources.\n\nModern Android applications need sophisticated UX-patterns such as *stale-while-revalidate*, *pull-to-refresh*, *pagination* and *optimistic updates*. Developers have to implement it over and over again without the right tool at hand.\n\nClassical imperative approach to networking is complex and error-prone. It is hard to achieve desired behavior by manually orchestrating individual network calls.\n\nTo summarize, Replica helps to:\n1. **Keep client data up to date**\n2. **Save server resources**\n3. **Create great UX**\n4. **Write simple and maintainable code**\n\n## Features\nReplica provides:\n- Declarative approach to networking\n- Independence from network frameworks (*Retrofit*, *Ktor*, *Apollo GraphQL* and so on)\n- Automatic data loading based on active screens\n- In-memory and on-disk caching\n- Stale time configuration with automatic refresh\n- Automatic request cancellation and old data clearing\n- Request deduplication\n- Sophisticated UX-patterns support\n- Reaction on network connection status changes\n- Combining data from several requests\n- Integration with [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel) and [Decompose](https://github.com/arkivanov/Decompose)\n- Visual debug tool integrated to Android Studio\n- KMM support\n- Pagination\n\n## Gradle Setup\n```gradle\ndependencies {\n\n    def replicaVersion = '1.4.0-alpha'\n\n    // Basic usage\n    implementation \"com.github.aartikov:replica-core:$replicaVersion\"\n\n    // Automatic reaction on changes of network connection status\n    implementation \"com.github.aartikov:replica-android-network:$replicaVersion\"\n\n    // Transforming and combining replicas\n    implementation \"com.github.aartikov:replica-algebra:$replicaVersion\"\n\n    // Integration with ViewModel library\n    implementation \"com.github.aartikov:replica-view-model:$replicaVersion\"\n\n    // Integration with Decompose library\n    implementation \"com.github.aartikov:replica-decompose:$replicaVersion\"\n\n    // Debug tool\n    debugImplementation \"com.github.aartikov:replica-devtools:$replicaVersion\"\n    releaseImplementation \"com.github.aartikov:replica-devtools-noop:$replicaVersion\"\n}\n```\n\n## How it works\nThe library is based on a concept called **data replication**. The idea is simple. There is some data on a server. A client needs this data. Replica automatically represent server data on a client side and keeps it in sync.\n\nReplica provides data replication primitives called **replicas**. Each replica targets some chunk of data on a server and replicates it on a client.\n\nAnd the last concept is **replica observers**. Replica observers are required to display data on UI. An observer connects to a replica and transfers its state to UI. A replica knows how many observers it has and performs complex behaviour based on this information.\n\n\u003cimg src=\"images/how_replica_works.png\"\u003e\n\n## Basic usage\nTypical code with Replica looks like that:\n\n1. **Create a replica in Repository**\n\n```kotlin\nclass PokemonRepository(\n    replicaClient: ReplicaClient,\n    api: PokemonApi\n) {\n\n    val pokemonsReplica: Replica\u003cList\u003cPokemon\u003e\u003e = replicaClient.createReplica(\n        name = \"pokemons\",\n        settings = ReplicaSettings(staleTime = 1.minutes),\n        fetcher = {\n            api.getPokemons().toDomain()\n        }\n    )\n}\n```\n\n2. **Observe a replica in ViewModel**\n```kotlin\nclass PokemonListViewModel(\n    private val pokemonsReplica: Replica\u003cList\u003cPokemon\u003e\u003e,\n    errorHandler: ErrorHandler\n) : ViewModel(), Activable by activable() {\n\n    val pokemonsState = pokemonsReplica.observe(this, errorHandler)\n\n}\n```\n\n3. **Display state on UI**\n```kotlin\nviewLifecycleOwner.lifecycleScope.launch {\n    repeatOnLifecycle(Lifecycle.State.STARTED) {\n        viewModel.pokemonsState.collect { state -\u003e\n            val (loading, data, error) = state\n            when {\n                data != null -\u003e {\n                    // show a list of pokemons\n                }\n                loading -\u003e {\n                    // show a fullscreen progress\n                }\n                error != null -\u003e {\n                    // show a fullscreen error\n                }\n            }\n        }\n    }\n}\n```\n\n## Replica DevTools\n\nReplica has a debug tool integrated to Android Studio. It allows to monitor replicas, their states and observers.\n\n\u003cimg src=\"images/replica_devtools_light.png\"\u003e\n\nOf course, dark theme is supported.\n\n\u003cimg src=\"images/replica_devtools_dark.png\"\u003e\n\n\n## Learn more\n### Samples\n- [Simple sample](https://github.com/aartikov/Replica/tree/main/simple-sample) - shows basic usage of Replica. \n- [Advanced sample](https://github.com/aartikov/Replica/tree/main/advanced-sample) - shows advanced techniques: observing data by dynamic key, optimistic updates, integration with [Decompose](https://github.com/arkivanov/Decompose). Architecture on this sample is based on [MobileUp Android Template](https://github.com/MobileUpLLC/MobileUp-Android-Template).\n\n### Documentation\n[Replica Documentation](https://aartikov.github.io/Replica/) - a website with detailed documentation (WIP).\n\n## Contact the author\nArtur Artikov\n\ntelegram - \u003ca href=\"https://t.me/aartikov\"\u003e@aartikov\u003c/a\u003e, email - \u003ca href=\"mailto:a.artikov@gmail.com\"\u003ea.artikov@gmail.com\u003c/a\u003e\n\n## Special thanks\nTo \u003ca href=\"https://github.com/EgoriusE\"\u003eEgor Belov\u003c/a\u003e for the help with Replica DevTools and Unit tests.\n\n## License\n```\nThe MIT License (MIT)\n\nCopyright (c) 2023 Artur Artikov, Egor Belov\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faartikov%2Freplica","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faartikov%2Freplica","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faartikov%2Freplica/lists"}