retained
Retained is a lightweight Kotlin Multiplatform library built on top of AndroidX ViewModel. It provides a unified API to retain object instances across Kotlin Multiplatform targets.
- Remove the need for
ViewModelinheritance. - Remove the need for
ViewModelProvider.Factory. - Provide direct access to
ViewModelproperties:CoroutineScope(viewModelScope),SavedStateHandle, and parameters. - Automatic resource management via
AutoCloseable.
Download
dependencies {
// Core Kotlin Multiplatform support
implementation 'dev.marcellogalhardo:retained-core:{Tag}'
// `Activity` support
implementation 'dev.marcellogalhardo:retained-activity:{Tag}'
// `Fragment` support (includes `Activity` support)
implementation 'dev.marcellogalhardo:retained-fragment:{Tag}'
// Navigation support
implementation 'dev.marcellogalhardo:retained-navigation:{Tag}'
// Navigation with Fragment support (includes `Navigation` support)
implementation 'dev.marcellogalhardo:retained-navigation-fragment:{Tag}'
// Compose support (Android, iOS, Desktop)
implementation 'dev.marcellogalhardo:retained-compose:{Tag}'
// View support (experimental)
implementation 'dev.marcellogalhardo:retained-view:{Tag}'
implementation 'dev.marcellogalhardo:retained-navigation-view:{Tag}'
}
(Replace {Tag} with the latest release version)
Usage
This section shows how to retain instances in activities and fragments. All examples use this class:
class Presenter(var counter: Int = 0)
Use Retained in Activities and Fragments
// Retain an instance in an Activity:
class CounterActivity : AppCompatActivity() {
private val presenter: Presenter by retain { Presenter() }
}
// Retain an instance in a Fragment:
class CounterFragment : Fragment() {
private val presenter: Presenter by retain { Presenter() }
}
// Share an instance between Fragments scoped to the Activity
class CounterFragment : Fragment() {
private val sharedPresenter: Presenter by retainInActivity { Presenter() }
}
// Share an instance between Fragments scoped to the NavGraph
class CounterFragment : Fragment() {
private val presenter: Presenter by retainInNavGraph(R.navigation.nav_graph) { Presenter() }
}
Use Retained in Compose
@Composable
fun CounterScreen() {
// Scope to LocalViewModelStoreOwner (default)
val presenter = retain { Presenter() }
// Scope to ComponentActivity (Android)
val activityPresenter = retainInActivity { Presenter() }
// Scope to a specific ViewModelStoreOwner (e.g. NavBackStackEntry)
val navBackStackEntry: NavBackStackEntry // Find NavBackStackEntry
val scopedPresenter = retain(owner = navBackStackEntry) { Presenter() }
}
Advanced Usage
Custom Parameters from Jetpack ViewModel
When you retain an instance, RetainedEntry provides access to host parameters.
@Composable
fun CounterScreen() {
val presenter = retain { entry: RetainedEntry ->
Presenter()
}
// ...
}
RetainedEntry provides a SavedStateHandle to save and restore state.
class CounterFragment : Fragment() {
private val presenter: Presenter by retain { entry ->
Presenter(counter = entry.savedStateHandle.get<Int>("count") ?: 0)
}
// ...
}
RetainedEntry provides a CoroutineScope that matches viewModelScope.
class Presenter(scope: CoroutineScope) { /* ... */ }
class SampleFragment : Fragment() {
private val presenter: Presenter by retain { entry ->
Presenter(scope = entry.coroutineScope)
}
// ...
}
For more details, see RetainedEntry.
Automatic Resource Management (AutoCloseable)
If a retained instance implements AutoCloseable, retained automatically closes it when the host ViewModel is cleared (ViewModel.onCleared).
class ResourcePresenter : AutoCloseable {
override fun close() {
// Automatically called when the host ViewModel is cleared
}
}
View Support (Experimental)
You can also retain instances in a View. Use these modules:
dependencies {
implementation 'dev.marcellogalhardo:retained-view:{Tag}'
implementation 'dev.marcellogalhardo:retained-navigation-view:{Tag}'
}
The retained-view module provides retain and retainInActivity to scope instances to an Activity or Fragment. The retained-navigation-view module provides retainInNavGraph to scope instances to a NavGraph.
License
Copyright 2019 Marcello Galhardo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
