• 一手遮天 Android jetpack: LiveData 基础,以及 LiveData 和 ViewModel 结合使用


    项目地址 https://github.com/webabcd/AndroidDemo
    作者 webabcd

    一手遮天 Android - jetpack: LiveData 基础,以及 LiveData 和 ViewModel 结合使用

    示例如下:

    /jetpack/lifecycle/LiveDataDemo.kt

    /**
     * LiveData
     * 本例用于演示如何通过 LiveData 实现数据变化的通知与接收,以及 LiveData 如何结合 ViewModel 使用
     *
     * LiveData
     *   当数据发生变化时,LiveData 会通知 Observer
     *   LiveData 会根据 Observer 绑定的 LifecycleOwner 的生命周期情况,来决定是否将数据的变化通知给 Observer(比如 activity 不在前台就不通知了)
     *   activity 不在前台就不通知,当 activity 返回前台时会先通知一次之前没能通知的最近一次的通知,然后继续正常的通知
     * ViewModel
     *   注重结合生命周期管理数据,发生 configuration change(比如横竖屏切换等)时不会销毁数据(关于 configuration change 请参见 /ui/ConfigurationChangeDemo1.java)
     *   当不需要 ViewModel 时,比如 activity 将要销毁时,此时绑定到此 activity 的 ViewModel 会自动调用自己的 onCleared() 方法,然后销毁自己
     * 官方建议 LiveData 和 ViewModel 配合使用,在 ViewModel 中使用 LiveData,这样当 ViewModel 销毁的时候,LiveData 就跟着销毁了
     *
     *
     * LiveData - 抽象类,其 postValue() 和 setValue() 是 protected 的
     * MutableLiveData - 继承自 LiveData,其 postValue() 和 setValue() 是 public 的
     *   setValue() - 更新 LiveData 的值,只能在主线程调用,新的值会通知给观察者
     *   postValue() - 更新 LiveData 的值,允许在非主线程调用,其内部会切换到主线程并调用 setValue(),新的值会通知给观察者
     *     注:在主线程接收数据之前,如果多次调用 postValue() 则主线程只会收到最后一次更新的数据的通知
     *   getValue() - 获取 LiveData 的值
     *   observe() - 在指定的 LifecycleOwner 中添加观察者
     *   removeObserver()/removeObservers() - 移除观察者
     *   observeForever() - 添加观察者,但是不绑定任何 LifecycleOwner(也就是说数据变化总是会通知给观察者,即使当前 activity 不在前台)
     *   hasObservers() - 是否有观察者
     *   hasActiveObservers() - 是否有活动观察者(即绑定的 LifecycleOwner 在前台,则观察者就是活动的)
     */
    
    package com.webabcd.androiddemo.jetpack.lifecycle
    
    import android.content.Intent
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.util.Log
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.MutableLiveData
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.ViewModelProvider
    import com.webabcd.androiddemo.R
    import kotlinx.android.synthetic.main.activity_jetpack_lifecycle_livedatademo.*
    import kotlinx.coroutines.*
    import java.text.SimpleDateFormat
    import java.util.*
    
    class LiveDataDemo : AppCompatActivity() {
    
        private lateinit var viewModel: MyViewModel
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_jetpack_lifecycle_livedatademo)
    
            // 创建一个指定的 ViewModel 对象,并绑定到指定的 activity
            viewModel = ViewModelProvider(this)[MyViewModel::class.java]
            // 为 ViewModel 中的 LiveData 指定观察者,并将这个观察者绑定到当前的 activity
            viewModel.myName.observe(this) {
                // 调用 LiveData 的 postValue() 或 setValue() 后,观察者就会收到通知
                textView1.text = it
    
                // 正常来说,这里每秒会收到一个通知,但是如果 activity 走到后台了,这里就收不到了
                // 当 activity 重新变回前台时,则会先收到之前没收到的最近一次的通知,之后会继续每秒都收到通知
                Log.d("lifecycle", it)
            }
    
            // 每秒更新一次 LiveData 的值
            CoroutineScope(Dispatchers.Default).launch {
                repeat(1000) {
                    delay(1000)
                    val dateFormat = SimpleDateFormat("HH:mm:ss.SSS", Locale.ENGLISH)
                    val time = dateFormat.format(Date())
                    viewModel.setMyName("$time")
                }
            }
    
            // 跳转到其他 activity 然后再返回来,观察一下这个过程中的效果
            button1.setOnClickListener {
                startActivity(Intent(this@LiveDataDemo, LifecycleDemo::class.java))
            }
        }
    }
    
    // 自定义 ViewModel
    class MyViewModel: ViewModel() {
    
        private val _myName = MutableLiveData<String>()
    
        val myName: LiveData<String>
            get() = _myName
    
        init {
            _myName.value = "webabcd"
        }
    
        fun setMyName(name: String) {
            _myName.postValue(name)
    
            // 只能在主线程调用 setValue()
            // _myName.value = name
        }
    
        // 当不需要 ViewModel 时,比如 activity 将要销毁时,此时绑定到此 activity 的 ViewModel 会自动调用自己的 onCleared() 方法,然后销毁自己
        // 如果需要的话,你可以在这里清理相关资源
        override fun onCleared() {
            super.onCleared()
        }
    }
    

    /layout/activity_jetpack_lifecycle_livedatademo.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:text="跳转到其他 activity"/>
    
        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </LinearLayout>
    
    

    项目地址 https://github.com/webabcd/AndroidDemo
    作者 webabcd

  • 相关阅读:
    如何提高逻辑思维的能力 思维的层次 逻辑思维能力练习方式
    淘宝JAVA中间件Diamond详解之简介&快速使用 管理持久配置的系统
    java 取模运算% 实则取余 简述 例子 应用在数据库分库分表
    SpringMVC+Spring+mybatis项目从零开始--Spring mybatis mysql配置实现
    SpringMVC+Spring+mybatis项目从零开始--分布式项目结构搭建
    JS密码校验规则前台验证(不能连续字符(如123、abc)连续3位或3位以上)(不能相同字符(如111、aaa)连续3位或3位以上)
    12 个非常实用的 jQuery 代码片段
    html增加和删除div
    css改变hr颜色
    jquery怎么在点击li标签之后添加一个在class,点击下一个li时删除上一个class?
  • 原文地址:https://www.cnblogs.com/webabcd/p/android_jetpack_lifecycle_LiveDataDemo.html
Copyright © 2020-2023  润新知