美文网首页Android
Jetpack(二)LiveData

Jetpack(二)LiveData

作者: Demon鑫 | 来源:发表于2020-09-02 13:15 被阅读0次

    二、LiveData

    1. 作用

    • LiveData 一个可观测的数据持有类
    • 数据可以被观察者订阅
    • 能够感知组件(Fragment、Activity、Service)的生命周期
    • 只有在组件出于激活状态才会通知观察者有数据更新

    2.优势

    • 确保UI和数据状态匹配
    当数据发生改变的时候,会自动通知UI进行更新
    • 避免内存泄漏
    Observers 绑定到 Lifecycle 对象上,当与其关联的 lifecycle 被销毁的时候,它们会自动被清理
    • 避免了由于 Activity 停止而导致的闪退
    Observer 绑定的 Lifecycle 处于非活跃状态时,不会收到任何 LiveData 事件
    • 不再需要手动处理生命周期
    LiveData 具有生命周期感知能力,它会自动对这些进行管理
    • 数据总处于最新状态
    Lifecycle 由非活跃状态变为活跃状态时,它将收到最新的数据
    • 系统配置更改时,进行数据的保存和恢复,及 UI 的恢复
    配合 ViewModel 可以规避旋转屏幕等问题
    • 资源共享
    可以使用单例模式来扩展 LiveData,这样能达到数据变化的时候,通知所有的观察者

    3. 使用
    3.1. 创建 LiveData

    • 创建 LiveData 实例,让其持有特定的数据类型
    • 通常是将 LiveData 放在 ViewModel 中使用

    // 1.创建 LiveData
    private val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }
    
    3.2. 创建 Observe

    • 创建 Observer 对象,并实现 onChanged() ,在此定义 LiveData 持有的数据改变时做何操作
    • 可在此更新 UI ,一般 Observer 在 UI controller 中创建,比如 Activity 或者 Fragment

    // 2.创建 Observe
    val nameObserver = Observer<String> { newName ->
        binding.data = newName
    }
    
    3.3. Observer 添加到 LiveData

    observe(LifecycleOwner owner, Observer observer)
    • owner : LifecycleOwner对象,LiveData 能监听生命周期的能力来源
    • observer : 监听器对象 Observer

    // 3.Observer 添加到 LiveData
    currentName.observe(this@MainActivity, nameObserver)
    
    3.4. 改变 LiveData 值

    • 在UI线程通过 value 改变 LiveData 值
    • 在子线程通过 postValue() 修改 LiveData 值

    // 点击时改变 LiveData 值
    binding.button.setOnClickListener {
        // 4.UI 线程通过 value 修改 LiveData 值
        currentName.value = "2234"
    }
    
    // 点击时改变 LiveData 值
    binding.button.setOnClickListener {
        Thread {
            var num = 0
            while (num < 5) {
                try {
                    Thread.sleep(1000)
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
                // 4.子线程通过 postValue() 修改 LiveData 值
                currentName.postValue((++num).toString())
            }
        }.start()
    }
    
    4. 其他
    4.1. 扩展 LiveData

    • 如需观察者处于 active 状态时做操作,可通过继承 LiveData 或者 MutableLiveData后复写onActive()onInactive()

    class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    
        private val stockManager = StockManager(symbol)
    
        // setValue(T) 方法将更新 LiveData 实例的值,并将更改通知给任何活跃观察者。
        private val listener = { price: BigDecimal ->
            value = price
        }
    
        // 当 LiveData 对象具有活跃观察者时,会调用 onActive() 方法。
        // 这意味着,您需要从此方法开始观察股价更新。
        override fun onActive() {
            stockManager.requestPriceUpdates(listener)
        }
    
        // 当 LiveData 对象没有任何活跃观察者时,会调用 onInactive() 方法。
        // 由于没有观察者在监听,因此没有理由与 StockManager 服务保持连接。
        override fun onInactive() {
            stockManager.removeUpdates(listener)
        }
    }
    
    4.2.转换 LiveData
    1. Transformations.map()
      • 可以通过Transformationsmap 操作符 修改数据
      • 可以将数据转换为其他类型

      // ====== Transformations.map 处理 类型转换 ======
      Transformations.map(currentName) {
          Function<String, String> { input -> "修改$input" }
      }.observe(this@MainActivity, { newName ->
          binding.data = newName.toString()
      })
      
      // ====== Transformations.map 处理 类型转换 (lambda简化后) ======
      Transformations.map(currentName) { input -> "修改$input" }.observe(this, { newName ->
          binding.data = newName
      })
      
    2. Transformations.switchMap()

      • 可以通过TransformationsswitchMap() 操作符 通过room 做数据查询等

      // ====== Transformations.map 处理 类型转换 ======
      val userLiveData = Transformations.switchMap(currentName, object : Function<String, LiveData<User>> {
          override fun apply(input: String?): LiveData<User> {
              // 根据 userId 返回一个 LiveData<User>,可通过 room 获取
              return dao.getUser()
          }
      })
      // ====== Transformations.map 处理 类型转换 (lambda简化后)  ======
      val userLiveDataL = Transformations.switchMap(currentName, Function<String, LiveData<User>> {
          // 根据 userId 返回一个 LiveData<User>,可通过 room 获取
          dao.getUser()
      })
      
    3. 自定义CustomTransformations
      • 如有更复杂需求可通过 MediatorLiveData 自定义 transformations
      Transformations 源码就是通过 MediatorLiveData 实现二次转发
      • 里面其实主要用的就是MediatorLiveData,通过该类能组合多个LiveData源。当任何一个LiveData源发生改变的时候,MediatorLiveDataObservers 都会被触发。比如有两个LiveData,一个是从数据库获取,一个是从网络获取。通过MediatorLiveData就能做到,当二者任何一个获取到最新数据,就去触发监听。

      public class Transformations {
      
          private Transformations() {
          }
      
          @MainThread
          @NonNull
          public static <X, Y> LiveData<Y> map(
                  @NonNull LiveData<X> source,
                  @NonNull final Function<X, Y> mapFunction) {
              final MediatorLiveData<Y> result = new MediatorLiveData<>();
              result.addSource(source, new Observer<X>() {
                  @Override
                  public void onChanged(@Nullable X x) {
                      result.setValue(mapFunction.apply(x));
                  }
              });
              return result;
          }
      
          @MainThread
          @NonNull
          public static <X, Y> LiveData<Y> switchMap(
                  @NonNull LiveData<X> source,
                  @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
              final MediatorLiveData<Y> result = new MediatorLiveData<>();
              result.addSource(source, new Observer<X>() {
                  LiveData<Y> mSource;
      
                  @Override
                  public void onChanged(@Nullable X x) {
                      LiveData<Y> newLiveData = switchMapFunction.apply(x);
                      if (mSource == newLiveData) {
                          return;
                      }
                      if (mSource != null) {
                          result.removeSource(mSource);
                      }
                      mSource = newLiveData;
                      if (mSource != null) {
                          result.addSource(mSource, new Observer<Y>() {
                              @Override
                              public void onChanged(@Nullable Y y) {
                                  result.setValue(y);
                              }
                          });
                      }
                  }
              });
              return result;
          }
      
          @MainThread
          @NonNull
          public static <X> LiveData<X> distinctUntilChanged(@NonNull LiveData<X> source) {
              final MediatorLiveData<X> outputLiveData = new MediatorLiveData<>();
              outputLiveData.addSource(source, new Observer<X>() {
      
                  boolean mFirstTime = true;
      
                  @Override
                  public void onChanged(X currentValue) {
                      final X previousValue = outputLiveData.getValue();
                      if (mFirstTime
                              || (previousValue == null && currentValue != null)
                              || (previousValue != null && !previousValue.equals(currentValue))) {
                          mFirstTime = false;
                          outputLiveData.setValue(currentValue);
                      }
                  }
              });
              return outputLiveData;
          }
      }
      

    Demo地址 : LiveData[module]

    2020年9月2日

    相关文章

      网友评论

        本文标题:Jetpack(二)LiveData

        本文链接:https://www.haomeiwen.com/subject/iozisktx.html