android Jetpack LiveData用法介绍

1,866 阅读4分钟

LiveData用法介绍

LiveData是Android Jetpack里的一个组件库,它具有感知activity和fragment生命周期的功能,使用观察者模式设置数据并确保数据在activity和fragment正确的生命周期内更新ui,提升app性能,并防止app crash

先来看一个非常简单的例子

class LiveDataActivity : AppCompatActivity() {

    var liveData: MutableLiveData<String>? = null
    var disposable: Disposable? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_livedata)
        liveData = MutableLiveData()
        // 观察数据的变化,只有在界面可见的时候才会回调(即onStart或onResume状态)
        liveData!!.observe(this, Observer {
            tv_text.text = it
        })

        loadData()
    }

    override fun onDestroy() {
        super.onDestroy()
        disposable?.dispose()
    }

    private fun loadData() {
        disposable = Flowable.interval(1, 1, TimeUnit.SECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                // 更新数据
                liveData?.value = it.toString()
            }
    }
}

LiveData的用法非常简单,首选new一个LiveData对象,然后通过observe方法添加一个Observer,并实现Observer接口的onChanged方法,最后在数据更新的时候使用livedatasetValue方法更新数据即可;调用setValue方法的时候,如果当前Activity处于onStartonResume状态,则会调用ObserveronChanged回调,否则先缓存数据,当Activity重新回到onStartonResume状态时,再调用ObserveronChanged回调(Activity destroy时 会自动remove Observer,所以不需要我们手动remove)

LiveData 几个比较重要的方法介绍

  • setValue(T value)

    必须在 UI Thread 中调用,更新数据,同时当Activity处于onStartonResume状态时会调用ObserveronChanged回调

  • postValue(T value)

    跟setValue()一样,唯一的区别就是可以 非UI Thread 中调用,然后通过handler post在UI Thread中回调

  • observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

    这是一个非常常用的方法, 用于添加一个Observer,监听数据的变化; LifecycleOwner 一般是activity 或 fragment对象,使其LiveData可以感知其生命周期,只有在onStartonResume状态时会调用ObserveronChanged回调, 在destroy时 remove Observer

  • observeForever(@NonNull Observer<? super T> observer)

    跟observe方法差不多,唯一的区别是没办法感知activity 或 fragment生命周期;即只要有数据更新就立马调用ObserveronChanged回调,并且需要手动remove Observer;这个方法对于Transformation(数据转换)非常有用,下面会介绍到

  • removeObservers(@NonNull final Observer<? super T> observer)

    这个方法很简单,就是删除某个observer

  • onActive()

    这是LiveData的一个回调方法,当observer的数量由0变成1的时候,会调用

  • onInactive()

    这是LiveData的一个回调方法,当observer的数量由1变成0的时候,会调用

MutableLiveData 介绍

MutableLiveData 比较简单,一般没什么特殊需求,用MutableLiveData就可以,他的源码实现也非常简单

public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

只是将LiveDataprotected修饰postValuesetValue的方法改成了public

用法就跟上面的demo一样

MediatorLiveData 介绍

MediatorLiveData继承MutableLiveData, 并提供addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged)方法监听LiveData的数据更新,然后做一层处理或直接通知给最外层的Observer

先看一下源码里的example, 只处理前10次数据的变化

LiveData<String> liveData1 = ...;
var liveDataMerger = MediatorLiveData<String>()
liveDataMerger.addSource(liveData1, object: Observer<String> {
    var count = 1
    override fun onChanged(t: String) {
        count++
        // 在这里更新liveDataMerger的数据;因此可以在这里对数据做一些额外的处理之后再更新
        liveDataMerger.value = t
        if (count > 10) {
            liveDataMerger.removeSource(liveData1)
        }
    }
})

同时它还可以监听多个LiveData的变化

val liveData1 = MutableLiveData<String>()
val liveData2 = MutableLiveData<String>()
var liveDataMerger = MediatorLiveData<String>()
liveDataMerger.addSource(liveData1, Observer { liveDataMerger.value = it })
liveDataMerger.addSource(liveData2, Observer { liveDataMerger.value = it })
// 只要liveData1和liveData2数据有更新就会通知Observer更新ui
liveDataMerger.observe(this, Observer {
    tv_text.text = it
})

其实MediatorLiveData最常用的用法是结合Transformation来使用,下面将介绍Transformation的用法

Transformation 转换

Transformation内部原理使用MediatorLiveData实现的

有的时候我们需要对当前data 转换成我们需要的另一种data

比如rxjavamap方法

Flowable.range(1, 10)
	.map { "index: $it" }
	.subscribe {
		
	}

再比如 kotlin自带的map扩展方法

val list = listOf(1, 2, 3, 4).map {
    "index: $it"
}

LiveData 也提供了类似的map功能

// 创建LiveData
val userLiveData: LiveData<User> = MutableLiveData<User>()
val userName: LiveData<String> = Transformations.map(userLiveData) {
    user -> "${user.name} ${user.lastName}"
}
//观察数据的更新
userName.observe(this, Observer {
    tv_text.text = it
})
...

// 更新数据
userLiveData.value = User("zhang", "san")

LiveData 也提供了switchMap方法转换数据,它与map唯一的不同是将data转换成一个LiveData<T>,因此在转换过程中可以继续做异步操作请求数据等,他跟rxjavaflatmap方法有点像

// 先使用room数据库定义一个UserDao example
@Dao
abstract class UserDao {
    @Query("select * from tab_user where uid = :uid")
    abstract fun getById(uid: Long): LiveData<User>
}	
...

private fun getUser(id: String): LiveData<User> {
	// 可以使用room数据查询user对象
   // return AppDataBase.getUserDao().getUser(id)
   // 你也可以发网络请求查询user对象
   return object: LiveData<User>() {
        override fun onActive() {
            super.onActive()
            // 模拟网络请求数据
            Flowable.timer(3, TimeUnit.SECONDS)
                .subscribe {
                    postValue(User("zhang", "san"))
                }
        }
    }
}

...
val userId: LiveData<String> = MutableLiveData<String>()
val user = Transformations.switchMap(userId) { id -> getUser(id) }

//观察数据的更新
user.observe(this, Observer {
    tv_text.text = "${it.name} ${it.name}"
})
...
// 更新数据
userId.value = "001"

LiveData使用起来比较简单,功能就介绍到这里,建议查看一下官方demo 学习结合其它library的用法