Android Kotlin . , (flows) , , , , ( , ) , .
, API Lifecycle.repeatOnLifecycle
Flow.flowWithLifecycle
.
. . .
, , buffer, conflate, flowOn shareIn, API, CoroutineScope.launch, Flow<T>.launchIn LifecycleCoroutineScope.launchWhenX, , Job, , . API , , .
: β , , .
, , callbackFlow:
// Implementation of a cold flow backed by a Channel that sends Location updates
fun FusedLocationProviderClient.locationFlow() = callbackFlow<Location> {
val callback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult?) {
result ?: return
try { offer(result.lastLocation) } catch(e: Exception) {}
}
}
requestLocationUpdates(createLocationRequest(), callback, Looper.getMainLooper())
.addOnFailureListener { e ->
close(e) // in case of exception, close the Flow
}
// clean up when Flow collection ends
awaitClose {
removeLocationUpdates(callback)
}
}
API , ! . :
class LocationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Collects from the flow when the View is at least STARTED and
// SUSPENDS the collection when the lifecycle is STOPPED.
// Collecting the flow cancels when the View is DESTROYED.
lifecycleScope.launchWhenStarted {
locationProvider.locationFlow().collect {
// New location! Update the map
}
}
// Same issue with:
// - lifecycleScope.launch { /* Collect from locationFlow() here */ }
// - locationProvider.locationFlow().onEach { /* ... */ }.launchIn(lifecycleScope)
}
}
lifecycleScope.launchWhenStarted
. , callbackFlow
. API lifecycleScope.launch
launchIn
, , ! .
API, , , callbackFlow
, . , - :
class LocationActivity : AppCompatActivity() {
// Coroutine listening for Locations
private var locationUpdatesJob: Job? = null
override fun onStart() {
super.onStart()
locationUpdatesJob = lifecycleScope.launch {
locationProvider.locationFlow().collect {
// New location! Update the map
}
}
}
override fun onStop() {
// Stop collecting when the View goes to the background
locationUpdatesJob?.cancel()
super.onStop()
}
}
, , ! Android, , . , !
Lifecycle.repeatOnLifecycle
, , , . 1) , 2) /, , , 3) ! , .
, API, , Lifecycle.repeatOnLifecycle
, lifecycle-runtime-ktx.
: API
lifecycle:lifecycle-runtime-ktx:2.4.0-alpha01
.
:
class LocationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create a new coroutine since repeatOnLifecycle is a suspend function
lifecycleScope.launch {
// The block passed to repeatOnLifecycle is executed when the lifecycle
// is at least STARTED and is cancelled when the lifecycle is STOPPED.
// It automatically restarts the block when the lifecycle is STARTED again.
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
// Safely collect from locationFlow when the lifecycle is STARTED
// and stops collection when the lifecycle is STOPPED
locationProvider.locationFlow().collect {
// New location! Update the map
}
}
}
}
}
repeatOnLifecycle
β , Lifecycle.State , , state
, , , state
.
, , , , repeatOnLifecycle
. , API onCreate
onViewCreated
, . :
class LocationFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// ...
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
locationProvider.locationFlow().collect {
// New location! Update the map
}
}
}
}
}
: viewLifecycleOwner
. DialogFragments
, View. DialogFragments
lifecycleOwner
.
: API
lifecycle:lifecycle-runtime-ktx:2.4.0-alpha01
.
!
repeatOnLifecycle
, , state
, , Lifecycle . : , repeatOnLifecycle
, , .
class LocationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create a coroutine
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
// Repeat when the lifecycle is RESUMED, cancel when PAUSED
}
// `lifecycle` is DESTROYED when the coroutine resumes. repeatOnLifecycle
// suspends the execution of the coroutine until the lifecycle is DESTROYED.
}
}
}
, locationFlow
, lifecycleScope.launch
, , , .
repeatOnLifecycle
, , - .
Flow.flowWithLifecycle
Flow.flowWithLifecycle
, . API repeatOnLifecycle
, , Lifecycle - .
class LocationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Listen to one flow in a lifecycle-aware manner using flowWithLifecycle
lifecycleScope.launch {
locationProvider.locationFlow()
.flowWithLifecycle(this, Lifecycle.State.STARTED)
.collect {
// New location! Update the map
}
}
// Listen to multiple flows
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
// As collect is a suspend function, if you want to collect
// multiple flows in parallel, you need to do so in
// different coroutines
launch {
flow1.collect { /* Do something */ }
}
launch {
flow2.collect { /* Do something */ }
}
}
}
}
}
: API
Flow.flowOn(CoroutineContext)
,Flow.flowWithLifecycle
CoroutineContext
, , . ,flowOn
,Flow.flowWithLifecycle
, . ,callbackFlow
.
API, , , ! , , , . , , : , . , , .
API MutableStateFlow
MutableSharedFlow
subscriptionCount
, , subscriptionCount
. , , , . , , UiState
, ViewModel
UI StateFlow
. ! , ViewModel
.
Flow.stateIn Flow.shareIn . WhileSubscribed() , ! , Eagerly Lazily , CoroutineScope, .
: API, , . API , : , . , .
Flow Jetpack Compose
Flow.collectAsState Compose State<T> (UI) Compose
. Compose
UI, , . Compose
, (View).
Compose
Flow.flowWithLifecycle
:
@Composable
fun LocationScreen(locationFlow: Flow<Flow>) {
val lifecycleOwner = LocalLifecycleOwner.current
val locationFlowLifecycleAware = remember(locationFlow, lifecycleOwner) {
locationFlow.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
}
val location by locationFlowLifecycleAware.collectAsState()
// Current location, do something with it
}
, remember, , locationFlow
lifecycleOwner
, , .
Compose . LaunchedEffect, , . Lifecycle.repeatOnLifecycle
, , , State
.
LiveData
, API LiveData, ! LiveData
Lifecycle
, . API Lifecycle.repeatOnLifecycle
Flow.flowWithLifecycle
!
API LiveData
, Kotlin. API , LiveData
. , , Dispatcher
, . LiveData
, UI.
StateFlow
, , , , LiveData, , . , StateFlow ! StateFlow
.
. . .
API Lifecycle.repeatOnLifecycle
Flow.flowWithLifecycle
Android.