{"id":15040929,"url":"https://github.com/marcellogalhardo/retained","last_synced_at":"2025-04-05T13:09:57.367Z","repository":{"id":41298232,"uuid":"228624344","full_name":"marcellogalhardo/retained","owner":"marcellogalhardo","description":"[ACTIVE] A lightweight alternative to Android's ViewModels. The easiest way to retain instances in Activities, Fragments or Composables.","archived":false,"fork":false,"pushed_at":"2024-01-28T17:52:44.000Z","size":486,"stargazers_count":325,"open_issues_count":3,"forks_count":10,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T12:11:19.446Z","etag":null,"topics":["android","kotlin","viewmodel"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcellogalhardo.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}},"created_at":"2019-12-17T13:37:09.000Z","updated_at":"2025-03-02T08:25:07.000Z","dependencies_parsed_at":"2024-01-28T18:51:35.938Z","dependency_job_id":null,"html_url":"https://github.com/marcellogalhardo/retained","commit_stats":{"total_commits":192,"total_committers":5,"mean_commits":38.4,"dds":"0.44791666666666663","last_synced_commit":"4d8dd68db72255dfaebb18d54e94f4a238e3e837"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellogalhardo%2Fretained","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellogalhardo%2Fretained/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellogalhardo%2Fretained/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellogalhardo%2Fretained/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcellogalhardo","download_url":"https://codeload.github.com/marcellogalhardo/retained/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339158,"owners_count":20923014,"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","kotlin","viewmodel"],"created_at":"2024-09-24T20:45:17.767Z","updated_at":"2025-04-05T13:09:57.346Z","avatar_url":"https://github.com/marcellogalhardo.png","language":"Kotlin","readme":"# Retained Instance\n\nA lightweight library built on top of Android Architecture Component ViewModel to simplify how UI Controllers (e.g., `Activity`, `Fragment` \u0026 `NavBackStackEntry`) retain instances on Android.\n\n- Eliminate `ViewModel` inheritance.\n- Eliminate `ViewModelProvider.Factory` need.\n- Easy access to `ViewModel` scoped properties: `CoroutineScope` (`viewModelScope`), `SavedStateHandle`, and many others.\n- Enable composition: callbacks can be listened with `OnClearedListener`.\n\n**Motivation:** Retained was originally created to share a `ViewModel` in Kotlin Multiplatform projects between Android \u0026 iOS with ease.\n\n## Download\n\n```gradle\ndependencies {\n    // `Activity` support\n    implementation 'dev.marcellogalhardo:retained-activity:{Tag}'\n\n    // `Fragment` support, includes `Activity` support\n    implementation 'dev.marcellogalhardo:retained-fragment:{Tag}'\n\n    // Navigation support\n    implementation 'dev.marcellogalhardo:retained-navigation:{Tag}'    \n\n    // Navigation with Fragment support, includes `Navigation` support\n    implementation 'dev.marcellogalhardo:retained-navigation-fragment:{Tag}'\n    \n    // Compose support\n    implementation 'dev.marcellogalhardo:retained-compose:{Tag}'\n    \n    // View support (experimental)\n    implementation 'dev.marcellogalhardo:retained-view:{Tag}'\n    implementation 'dev.marcellogalhardo:retained-navigation-view:{Tag}'\n}\n```\n\n(Please replace `{Tag}` with the [latest version numbers](https://github.com/marcellogalhardo/retained/releases))\n\n## Usage\n\nThe following sections demonstrate how to retain instances in activities and fragments. For simplicity, all examples will retain the following class:\n\n```kotlin\nclass ViewModel(var counter: Int = 0)\n```\n\n### Use Retained in Activities and Fragments\n\n```kotlin\n// retain an instance in an Activity:\nclass CounterActivity : AppCompatActivity() {\n    private val viewModel: ViewModel by retain { ViewModel() }\n}\n\n// retain an instance in a Fragment:\nclass CounterFragment : Fragment() {\n    private val viewModel: ViewModel by retain { ViewModel() }\n}\n\n// share an instance between Fragments scoped to the Activity\nclass CounterFragment : Fragment() {\n    private val sharedViewModel: ViewModel by retainInActivity { ViewModel() }\n}\n\n// share an instance between Fragments scoped to the NavGraph\nclass CounterFragment : Fragment() {\n    private val viewModel: ViewModel by retainInNavGraph(R.navigation.nav_graph) { ViewModel() }\n}\n```\n\n### Compose Support\n\n```kotlin\n@Composable\nfun SampleView() {\n    val viewModel = retain { ViewModel() }\n    \n    val activity: ComponentActivity // find Activity\n    val viewModel = retain(owner = activity) { ViewModel() }\n    \n    val fragment: Fragment // find Fragment\n    val viewModel = retain(owner = fragment) { ViewModel() }\n    \n    val navBackStackEntry: NavBackStackEntry // find NavBackStackEntry\n    val viewModel = retain(owner = navBackStackEntry) { ViewModel() }\n}\n```\n\n### Advanced usage\n\n#### Custom parameters from Jetpack's ViewModel\n\nWhen retaining an instance, you have access to a `RetainedEntry` which contains all parameters you might need.\n\n```kotlin\n@Composable\nfun SampleView() {\n    val viewModel = retain { entry: RetainedEntry -\u003e\n        ViewModel()\n    }\n    // ...\n}\n```\n\nThe entry exposes a `SavedStateHandle` that can be used to work with the saved state, just like in a regular Android `ViewModel`.\n\n```kotlin\nclass CounterFragment : Fragment() {\n    private val viewModel: ViewModel by retain { entry -\u003e \n        ViewModel(counter = entry.savedStateHandle.get\u003cInt\u003e(\"count\"))\n    }\n    // ...\n}\n```\n\nIt also exposes a `CoroutineScope` that works just like `viewModelScope` from the Android `ViewModel`.\n\n```kotlin\nclass Presenter(scope: CoroutineScope) { /* ... */ }\n\nfun SampleFragment() {\n    private val presenter: Presenter by retain { entry -\u003e \n        Presenter(scope = entry.scope)\n    }\n    // ...\n}\n```\n\nFor more details, see `RetainedEntry`.\n\n#### Listening `onCleared` calls\n\nWhen retaining an instance, you can use the `RetainedEntry` to be notified when a retained instance is cleared (`ViewModel.onCleared`).\n\n```kotlin\n@Composable\nfun SampleView() {\n    val viewModel = retain { entry -\u003e\n        entry.onClearedListeners += {\n            println(\"Invoked when the host 'ViewModel.onCleared' is called\")\n        }\n        // ...\n    }\n    // ...\n}\n```\n\nAs a convenience, if the retained instance implements the `OnClearedListener` interface, it will be automatically added to `onClearedListeners` and notified.\n\n#### View support (experimental)\n\nBesides Activities and Fragments, it's also possible to retain instances in a view. There are a couple of extra modules for that:\n\n```gradle\ndependencies {\n    implementation 'dev.marcellogalhardo:retained-view:{Tag}'\n    implementation 'dev.marcellogalhardo:retained-navigation-view:{Tag}'\n}\n```\n\nThe `retained-view` module exposes `retainInActivity` and `retain`, which will scope the instance to the parent being it an activity or a fragment. The `retained-view-navigation` module exposes `retainInNavGraph` to retain instances scoped to the `NavGraph`.\n\nLicense\n-------\n\n    Copyright 2019 Marcello Galhardo\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcellogalhardo%2Fretained","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcellogalhardo%2Fretained","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcellogalhardo%2Fretained/lists"}