Android LiveData使用

LiveData是一个可观察的数据持有者类。 与常规observable不一样,LiveData是生命周期感知的,当生命周期处于STARTED或RESUMED状态,则LiveData会将其视为活动状态,这意味着它尊重其余应用程序组件的生命周期,例如Activity,Fragment或Service。
LiveData具备如下优势:java

  • UI和数据保持一致:遵循观察者模式,生命周期状态更改时,LiveData会通知Observer对象
  • 避免内存泄漏:观察者绑定到Lifecycle对象,并在其相关生命周期被破坏后自行清理
  • 不会因stop而崩溃:处于非活动状态,不会接收到LiveData事件,如Activity变为不可见
  • 自动感知生命周期:LiveData自动管理在观察时意识到相关的生命周期状态变化。
  • 数据始终保持最新:生命周期变为非活动状态再次变为活动状态时接收最新数据。 例如,Activity不可见变为可见时当即接收最新数据
  • 解决Configuration changes问题:当屏幕旋转或者回收时,从新建立Activity或Fragment,能够即时收到数据变动
  • 共享资源:使用单例扩展LiveData,就可在app中共享它
  • gradle配置
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
  • 建立LiveData对象
class TestViewModel : ViewModel() {
    private lateinit var userName: MutableLiveData<String>

    fun getUserName(): MutableLiveData<String> {
        if (!::userName.isInitialized) {
            userName = MutableLiveData()
            loadUsers()
        }
        return userName
    }

    private fun loadUsers() {
        userName.value = "test"
    }
}
  • 观察和变动LiveData对象
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var model = ViewModelProviders.of(this).get(TestViewModel::class.java)
        model.getUserName().observe(this, Observer {
            txt_test.text = it
        })// 观察
        btn_test.setOnClickListener {
            model.getUserName().value = "test 2"
        }// 变动
    }
}

在变动数据的使用有两种方式可用,一个是setValue,另一个是postValue,区别是setValue只能在主线程处理,postValue能够在子线程处理。android

  • LiveData结合Databinding使用
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        var model = ViewModelProviders.of(this).get(TestViewModel::class.java)
        binding.let {
            it.data = model
            it.setLifecycleOwner(this)
        }
        btn_test.setOnClickListener {
            model.getUserName().value = "test 2"
        }
    }
}

binding对象须要调用setLifecycleOwner(LifecycleOwner lifecycleOwner)设置lifecycleOwner对象。app

  • 扩展LiveData

一般LiveData只关心观察者的STARTED或RESUMED状态,下面代码片断扩展了LiveDataide

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private var mStockManager: StockManager? = null

    private val mListener = object : SimplePriceListener() {
        fun onPriceChanged(price: BigDecimal) {
            value = price
        }
    }

    init {
        mStockManager = StockManager(symbol)
    }

    override fun onActive() {
        mStockManager.requestPriceUpdates(mListener)
    }

    override fun onInactive() {
        mStockManager.removeUpdates(mListener)
    }
}

实现包括如下重要方法:post

  • 当 LiveData 对象具备活跃观察者时,会调用 onActive() 方法。这意味着,您须要今后方法开始观察数据更新。
  • 当 LiveData 对象没有任何活跃观察者时,会调用 onInactive() 方法。因为没有观察者在监听,所以没有理由与 StockManager 服务保持链接。
  • setValue(T) 方法将更新 LiveData 实例的值,并将更改通知给任何活跃观察者。
  • 使用扩展LiveData
class TestFragment : Fragment() {

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        val stockLiveData = StockLiveData("")
        stockLiveData.observe(this, Observer {
            // update UI
        })
    }
}

observe() 方法将传递 Fragment(它是 LifecycleOwner 的实例)做为第一个参数。这样作表示此观察者绑定到与全部者关联的 Lifecycle 对象,这意味着:gradle

  • 若是 Lifecycle 对象未处于活跃状态,那么即便值发生更改,也不会调用观察者。
  • 销毁 Lifecycle 对象后,会自动移除观察者

固然能够在多个 Activity、Fragment 和 Service 之间共享它们,只须要把 StockLiveData类实现为单例。this

  • 转换 LiveData

LiveData 对象分派给观察者以前对存储在其中的值进行更改,或者您可能须要根据另外一个实例的值返回不一样的 LiveData 实例。其提供了如下方法进行转换线程

  • Transformations.map()
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});
  • Transformations.switchMap()
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

要实现您本身的转换,可使用 MediatorLiveData 类,该类能够监听其余 LiveData 对象并处理它们发出的事件,其能够正确地将其状态传播到源 LiveData 对象。code

相关文章
相关标签/搜索