探索Android LiveData的使用和行为

Android LiveData是可观察和生命周期感知的数据。

假设生命周期所有者是一个活动,生命周期感知意味着它只在活动处于活动状态时向UI发送更新。Activity is active表示UI在后台(已启动状态)或在前台(恢复状态)可见。

基本LiveData用法

创建可变LiveData

class LiveDataViewModel: ViewModel() {

    private val _liveData = MutableLiveData<Int>()
    val liveData: LiveData<Int> = _liveData
   /*...*/
}
viewModelScope.launch {
    repeat(10000) { value ->
        delay(1000)
        _liveData.value = value
    }
}

MutableLiveData.postValue()

viewModelScope.launch(Dispatchers.IO) {
    repeat(10000) { value ->
        delay(1000)    
        _liveData.postValue(value)
    }
}

协同程序用于模拟异步流,因为我们不想阻塞UI/main线程。
setValue()必须在主线程上运行, postValue()可以在主线程或后台线程上
Observe LiveData - observe() / observeAsState()
观察LiveData,您可以使用手动观察LiveData.observe()或LiveData.observeAsState()应用程序编程接口

LiveData.observe()

创建MutableState数据
创建Observer对象
观察LiveData
移除Observer对象来自LiveData

@Composable
fun LiveDataScreen() {
    val viewModel: LiveDataViewModel = viewModel()
    val lifecycleOwner = LocalLifecycleOwner.current

    //(1) Create a MutableState data
    val manualObserveLiveDataState:MutableState<Int?> = 
        remember { mutableStateOf(null) }

    //(2) Create an observer object
    val liveDataObserver = remember {
        Observer<Int> { value ->
            manualObserveLiveDataState.value = value
        }
    }

    Column {

        Button(onClick = {
            //(3) Observe the LiveData
            viewModel.liveData.observe(lifecycleOwner, liveDataObserver)
        }) {
            Text(text = "Manually Start Observe LiveData")
        }

        Button(onClick = {
            // (4) Remove the observer from LiveData
            viewModel.liveData.removeObserver(liveDataObserver)
        }) {
            Text(text = "Manually Remove Observer")
        }
    }
}

在上面的步骤2中,remember {}创建观察员对象,这样我们就不会重新创建Observer对象在重新配置期间的每次。我犯了这个错误。因此,它会导致内存泄漏观察者的增长。

LiveData.observeastate()

@Composable
fun LiveDataScreen() {
    val viewModel: LiveDataViewModel = viewModel()

    // Create MutableState by observing the LiveData
    val observeAsStateLiveData = 
        viewModel.liveData.observeAsState(initial = null)

}
在内部,它调用DisposableEffect()副作用。其中最重要的是 onDispose()负责移除Observer对象在效果离开合成时自动为您生成。

@Composable
fun <R, T : R> LiveData<T>.observeAsState(initial: R): State<R> {
    val lifecycleOwner = LocalLifecycleOwner.current
    val state = remember { mutableStateOf(initial) }

    DisposableEffect(this, lifecycleOwner) {
        val observer = Observer<T> { state.value = it }

        observe(lifecycleOwner, observer)
        onDispose { removeObserver(observer) }
    }
    return state
}

研究setValue()与postValue()的行为

研究行为setValue()与 postValue(),可以尝试以下几种情况:

活动已创建/停止(在后台不可见)
活动已启动/暂停(在后台可见)
活动已恢复(在前台可见)
用户界面忙时
在主线程中运行postValue()
模拟用户界面正忙
要模拟UI繁忙,您可以快速发出该值

job = viewModelScope.launch {
    repeat(10000) { value ->
         delay(1)
        _liveData.postValue = value
    }
}
Button(onClick = {
    Thread.sleep(3000)
}) {
    Text(text = "Simulate Busy UI")
}

模拟活动暂停

要模拟某个活动暂停/失去焦点,可以在当前应用程序上启动另一个透明活动。

在观察者对象中添加登录

为了证明数据已发送到UI,您将以下日志记录添加到Observer对象

val liveDataObserver = remember {
    Observer<Int> { value ->
        Log.d(tag, "[ManualObserver]: Assigning $value to manualObserveLiveDataState.value")
        manualObserveLiveDataState.value = value
    }
}

setValue()与postValue()

在执行各种场景后,以下是setValue()和 postValue()

研究observe()与observeAsState()的行为

如果你使用observe(),您需要手动调用移除观察者()应用程序编程接口。如果你使用observeAsState()(使用 有效效果在内部),它会自动调用removeObserver()当 有效效果离开作文。

以下是要尝试的场景:

活动已创建/停止(在后台不可见)
活动已启动/暂停(在后台可见)
活动已恢复(在前台可见)
屏幕旋转被破坏
离别作文

模拟离开构图

要模拟离开组合,可以实现CommonScreen()下面的可组合功能,包含隐藏和显示实际可组合的按钮内容.当content是隐藏的,它模拟离开的构图。

@Composable
fun CommonScreen(content: @Composable () -> Unit) {
    var showContent by rememberSaveable { mutableStateOf(true) }
    val context = LocalContext.current

    Column(modifier = Modifier.verticalScroll(rememberScrollState())){
        if (showContent) {
            content()

            Button(onClick = {
                showContent = false
            }) {
                Text("Hide Content (Simulate Leaving Composition)")
            }
        }
        else {
            Button(onClick = {
                showContent = true
            }) {
                Text("Show Content")
            }
        }
    }
}

在observeastate()中添加日志记录

让我们复制LiveData.observeAsState到LiveData.observeAsStateWithLogging()带有日志信息的扩展函数,用于指示是否将数据发送到UI。

@Composable
fun <R, T: R> LiveData<T>.observeAsStateWithLogging(initial: R): State<R> {
    /*...*/
    DisposableEffect(this, lifecycleOwner) {
        val observer = Observer<T> {
            Log.d(tag, "[ObserveAsState]: Assigning $it to state.value")
            state.value = it
        }
        /*...*/
    }
    return state
}

LiveData生命周期

这个LiveData生命周期与ViewModel,因为ViewModel与活动生命周期相关联(在本例中), 视图模型在活动完成/应用程序退出时销毁。这个LiveData只有在ViewModel被摧毁了。所以只要应用程序是活动的setValue()或 postValue()即使活动未处于活动状态(例如,活动在后台不可见),也会持续发出数据。

这是在本应用程序中保持后台打印的日志记录示例:

[ViewModel]: setValue with 1167

取决于是否使用了导航组件ViewModel生命周期并不总是与活动生命周期相关联。
结论
关于LiveData具有活动生命周期意识,当UI不可见(创建/停止)时,它不会浪费任何资源。 LiveData当活动被破坏时,还会自动删除所有观察者。

但是,离开合成是不起作用的(因为活动仍然是活动/可见的)。为了节省资源,可以使用observeAsState()(当然,对于Jetpack Compose)它会自动删除Observer当它不再在构图循环中时显式。因此,不会向UI发送更新。

使用呢setValue()或 postValue() ?我个人更喜欢用setValue()因为当用户界面很忙时,它不会删除任何数据。我可以将数据获取放入后台线程并更新LiveData在主线程中,所以不删除任何数据,并且仍然保持异步。

以上内容的练习资料或其他Android学习资料可以点击下方卡片获取!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值