• LiveData 的使用和原理


    1. 自动获取绑定 ViewID 的插件库
      1.1 Application module 中 build.gradle中 添加

    1. apply plugin: 'org.jetbrains.kotlin.android'
    2. apply plugin: 'org.jetbrains.kotlin.android.extensions'

      1.2 项目 build.gradle 中添加

    1. plugins {
    2. id "org.jetbrains.kotlin.android.extensions" version '1.7.10' apply false
    3. id "org.jetbrains.kotlin.kapt" version '1.7.10' apply false
    4. }

    2. dependencies 中引用的库

    1. implementation 'androidx.lifecycle:lifecycle-livedata:2.5.1'
    2. implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
    3. kapt "androidx.lifecycle:lifecycle-common-java8:2.5.1"

    3. 示例代码
      3.1 activity_live_data.xml 布局文件

    1. <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    2. android:layout_width="match_parent"
    3. android:layout_height="match_parent">
    4. <androidx.appcompat.widget.LinearLayoutCompat
    5. android:layout_width="match_parent"
    6. android:layout_height="match_parent"
    7. android:gravity="center_horizontal"
    8. android:orientation="vertical"
    9. android:padding="10dp">
    10. <androidx.appcompat.widget.AppCompatTextView
    11. android:layout_width="wrap_content"
    12. android:layout_height="wrap_content"
    13. android:text="LiveData使用演示" />
    14. <androidx.appcompat.widget.AppCompatTextView
    15. android:id="@+id/tv_live_data_activity"
    16. android:layout_width="wrap_content"
    17. android:layout_height="wrap_content"
    18. android:text="当前liveData的值: " />
    19. <androidx.appcompat.widget.AppCompatTextView
    20. android:id="@+id/tv_mapped_data_activity"
    21. android:layout_width="wrap_content"
    22. android:layout_height="wrap_content"
    23. android:text="Map后liveData值: "
    24. android:textColor="@color/teal_700" />
    25. <FrameLayout
    26. android:id="@+id/fl_container_live"
    27. android:layout_width="match_parent"
    28. android:layout_height="300dp"
    29. android:layout_marginTop="20dp"
    30. android:background="@android:color/darker_gray" />
    31. <androidx.appcompat.widget.AppCompatButton
    32. android:id="@+id/btn_create_fg_live"
    33. android:layout_width="wrap_content"
    34. android:layout_height="wrap_content"
    35. android:layout_marginTop="10dp"
    36. android:padding="5dp"
    37. android:text="显fragment" />
    38. <androidx.appcompat.widget.AppCompatButton
    39. android:id="@+id/btn_destroy_fg_live"
    40. android:layout_width="wrap_content"
    41. android:layout_height="wrap_content"
    42. android:layout_marginTop="20dp"
    43. android:padding="5dp"
    44. android:text="隐fragment" />
    45. <LinearLayout
    46. android:layout_width="match_parent"
    47. android:layout_height="wrap_content"
    48. android:layout_marginTop="20dp"
    49. android:orientation="horizontal">
    50. <Button
    51. android:id="@+id/btn_change_live"
    52. android:layout_width="0dp"
    53. android:layout_height="wrap_content"
    54. android:layout_weight="1"
    55. android:padding="5dp"
    56. android:text="变LiveData" />
    57. <Button
    58. android:id="@+id/btn_change1_live"
    59. android:layout_width="0dp"
    60. android:layout_height="wrap_content"
    61. android:layout_weight="1"
    62. android:padding="5dp"
    63. android:text="变LiveOne" />
    64. <Button
    65. android:id="@+id/btn_change2_live"
    66. android:layout_width="0dp"
    67. android:layout_height="wrap_content"
    68. android:layout_weight="1"
    69. android:padding="5dp"
    70. android:text="变LiveTwo" />
    71. LinearLayout>
    72. androidx.appcompat.widget.LinearLayoutCompat>
    73. androidx.core.widget.NestedScrollView>

      3.2 LiveActivity.kt 

    1. /**
    2. * LiveData 的示例
    3. */
    4. class LiveActivity : AppCompatActivity() {
    5. private val TAG: String = "LiveActivity"
    6. //声明变量live data
    7. val liveAppleData = MutableLiveData()
    8. private val liveMappedData = liveAppleData.map {
    9. Pair<Int, String>(it.hashCode(), it)
    10. }
    11. val liveOne = MutableLiveData()
    12. val liveTwo = MutableLiveData()
    13. val mediatorLive = MediatorLiveData>()
    14. override fun onCreate(savedInstanceState: Bundle?) {
    15. super.onCreate(savedInstanceState)
    16. setContentView(R.layout.activity_live_data)
    17. val appleFragment = AppleFragment()
    18. supportFragmentManager.beginTransaction().add(R.id.fl_container_live, appleFragment)
    19. .commit()
    20. //TODO hide 和 show 不会改变 fragment 的生命周期状态,所以用 attach detach
    21. //显示 fragment attach
    22. btn_create_fg_live.setOnClickListener {
    23. supportFragmentManager.beginTransaction().attach(appleFragment).commit()
    24. Log.i(TAG, "onCreate: 显示fg ${appleFragment.isVisible}")
    25. }
    26. //隐藏 fragment detach
    27. btn_destroy_fg_live.setOnClickListener {
    28. supportFragmentManager.beginTransaction().detach(appleFragment).commit()
    29. Log.w(TAG, "onCreate 隐藏 fg ${appleFragment.isVisible}")
    30. }
    31. //变更livedata的值
    32. btn_change_live.setOnClickListener {
    33. liveAppleData.value = "当前 liveData 的值: ${System.currentTimeMillis()}"
    34. }
    35. btn_change1_live.setOnClickListener {
    36. liveOne.value = "one: ${System.currentTimeMillis().toString().takeLast(6)}"
    37. }
    38. btn_change2_live.setOnClickListener {
    39. liveTwo.value = "two ${System.currentTimeMillis().toString().takeLast(6)}"
    40. }
    41. //观察者
    42. liveAppleData.observe(this, Observer {
    43. tv_live_data_activity.text = it
    44. Log.i(TAG, "LiveData在LiveActivity中 $it")
    45. })
    46. //map转换后的数值
    47. liveMappedData.observe(this, Observer {
    48. tv_mapped_data_activity.text = it.toString()
    49. Log.i(TAG, "LiveData在LiveActivity 中 map 后 $it")
    50. })
    51. //中介者
    52. mediatorLive.addSource(liveOne) {
    53. Log.i(TAG, "LiveActivity中 LiveOne ---> $it")
    54. mediatorLive.value = "one >>" to it
    55. }
    56. mediatorLive.addSource(liveTwo) {
    57. Log.i(TAG, "LiveActivity中 LiveTwo ---> $it")
    58. mediatorLive.value = "two >>>>> " to it
    59. }
    60. mediatorLive.observe(this, Observer {
    61. Log.w(TAG, "LiveActivity中 mediatorLive ---> $it")
    62. })
    63. }
    64. }

    4. 内部Fragment
      4.1 fg_apple.xml 布局文件

    1. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. xmlns:app="http://schemas.android.com/apk/res-auto"
    3. xmlns:tools="http://schemas.android.com/tools"
    4. android:layout_width="match_parent"
    5. android:layout_height="match_parent">
    6. <androidx.appcompat.widget.AppCompatTextView
    7. android:layout_width="wrap_content"
    8. android:layout_height="wrap_content"
    9. android:text="Apple Fragment"
    10. android:textColor="@color/red"
    11. app:layout_constraintBottom_toBottomOf="parent"
    12. app:layout_constraintEnd_toEndOf="parent"
    13. app:layout_constraintStart_toStartOf="parent"
    14. app:layout_constraintTop_toTopOf="parent"
    15. app:layout_constraintVertical_bias="0.3" />
    16. <androidx.appcompat.widget.AppCompatTextView
    17. android:id="@+id/tv_live_apple"
    18. android:layout_width="wrap_content"
    19. android:layout_height="wrap_content"
    20. android:textSize="20sp"
    21. app:layout_constraintBottom_toBottomOf="parent"
    22. app:layout_constraintEnd_toEndOf="parent"
    23. app:layout_constraintStart_toStartOf="parent"
    24. app:layout_constraintTop_toTopOf="parent"
    25. tools:text="Apple Data" />
    26. <androidx.appcompat.widget.AppCompatTextView
    27. android:id="@+id/tv_mapped_live_apple"
    28. android:layout_width="wrap_content"
    29. android:layout_height="wrap_content"
    30. android:textColor="@android:color/holo_green_light"
    31. android:textSize="14sp"
    32. app:layout_constraintBottom_toBottomOf="parent"
    33. app:layout_constraintEnd_toEndOf="parent"
    34. app:layout_constraintStart_toStartOf="parent"
    35. app:layout_constraintTop_toTopOf="parent"
    36. app:layout_constraintVertical_bias="0.6"
    37. tools:text="Mapped Apple Data" />
    38. <androidx.appcompat.widget.AppCompatTextView
    39. android:id="@+id/tv_media_live_apple"
    40. android:layout_width="wrap_content"
    41. android:layout_height="wrap_content"
    42. android:textColor="@android:color/holo_blue_light"
    43. android:textSize="14sp"
    44. app:layout_constraintBottom_toBottomOf="parent"
    45. app:layout_constraintEnd_toEndOf="parent"
    46. app:layout_constraintStart_toStartOf="parent"
    47. app:layout_constraintTop_toTopOf="parent"
    48. app:layout_constraintVertical_bias="0.7"
    49. tools:text="mediator Apple Data" />
    50. <androidx.appcompat.widget.AppCompatTextView
    51. android:id="@+id/tv_switch_live_apple"
    52. android:layout_width="wrap_content"
    53. android:layout_height="wrap_content"
    54. android:textColor="@android:color/holo_red_dark"
    55. android:textSize="14sp"
    56. app:layout_constraintBottom_toBottomOf="parent"
    57. app:layout_constraintEnd_toEndOf="parent"
    58. app:layout_constraintStart_toStartOf="parent"
    59. app:layout_constraintTop_toTopOf="parent"
    60. app:layout_constraintVertical_bias="0.8"
    61. tools:text="Switch Apple Data" />
    62. androidx.constraintlayout.widget.ConstraintLayout>

      4.2 AppleFragment.kt

    1. class AppleFragment : Fragment() {
    2. private val TAG: String = "AppleFragment"
    3. override fun onCreateView(
    4. inflater: LayoutInflater,
    5. container: ViewGroup?,
    6. savedInstanceState: Bundle?
    7. ): View? {
    8. return inflater.inflate(R.layout.fg_apple, container, false)
    9. }
    10. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    11. super.onViewCreated(view, savedInstanceState)
    12. }
    13. override fun onResume() {
    14. super.onResume()
    15. Log.i(TAG, "onResume()")
    16. (requireActivity() as LiveActivity).apply {
    17. liveAppleData.observe(viewLifecycleOwner, Observer {
    18. tv_live_apple.text = it
    19. Log.i(TAG, "tv_live_apple 显示 ${tv_live_apple.isVisible}")
    20. Log.i(TAG, "LiveData 在 AppleFragment中: $it")
    21. })
    22. val liveMapApple = liveAppleData.map {
    23. Log.i(TAG, "LiveData 在 AppleFragment中 map: $it")
    24. "it mapped it ${it.takeLast(4)}"
    25. }
    26. //在inActive状态下,是不会感知数据的,但是一旦resume,就会得到最新的数据
    27. liveMapApple.observe(viewLifecycleOwner, Observer {
    28. val s = "mapped it: $it"
    29. tv_mapped_live_apple.text = s
    30. Log.w(TAG, "LiveData 在 AppleFragment中 map 后的数据 $it")
    31. })
    32. //mediator
    33. mediatorLive.observe(viewLifecycleOwner, Observer {
    34. //如果在inactive状态下,one two都变化了,它 resume 后只接受最新的
    35. val s = "mediator it $it"
    36. tv_media_live_apple.text = s
    37. Log.w(TAG, "AppleFragment中 mediatorLive ---> $it")
    38. })
    39. //switch map 结合 mediator, 通过条件,控制选择数据源,这里模拟的是,it的数字奇偶,控制最终输出
    40. val swLive = mediatorLive.switchMap {
    41. if (it.second.takeLast(1).toInt() % 2 == 0) liveOne else liveTwo
    42. }
    43. //UI可以看出,不论是 One,还是 Two,改变的话,只有满足条件,才会生效
    44. swLive.observe(viewLifecycleOwner, Observer {
    45. tv_switch_live_apple.text = it
    46. Log.w(TAG, "AppleFragment中 switchMap ---> $it")
    47. })
    48. }
    49. }
    50. }

  • 相关阅读:
    FFmpeg的makefile逻辑分析
    汇编语言快速回顾(以x86_64为例)
    树莓派通过网线连接电脑(校园网也能连接),实现SSH连接
    Python 获取 NCBI 基因名 SSL 证书出现异常?
    从0开始python学习-28.selenium 需要图片验证的登录
    RK3128-android7.1-rtl8723du
    1091:求阶乘的和(信奥一本通)
    讲讲存档文件的包装设计
    使用 Sealos 一键私有化部署 Serverless 框架 Laf
    论文笔记:SAITS: SELF-ATTENTION-BASED IMPUTATION FOR TIMESERIES
  • 原文地址:https://blog.csdn.net/u011193452/article/details/126285634