一、LiveData是什么?
LiveData是可观察数据存储器类,与常规可观察数据存储类不同,LiveData具有对系统组件(如:Activity、Fragment、Service等)的生命周期感知能力。
LiveData只有在生命周期的活跃状态下才会更新数据,即start、resume,非活跃状态pause、stop是不会更新数据的。如下所示:
LiveData只有在活跃状态下才会通知更新数据,也就是start和resume生命周期状态下,当组件进入onPause或者onStop生命周期状态下,当前组件非活跃状态下不会通知更新数据,在非活跃状态下有ViewModel有数据更新,在组件状态从onPause或者onStop非活跃状态进入活跃状态onStart或者onResume下,会通知组件数据更新。
1 D/Test: start 2 D/Test: resume 3 D/Test: update data: 1 4 D/Test: pause 5 D/Test: stop 6 D/Test: changed value print // Model更新数据但未通知组件更新数据 7 D/Test: start 8 D/Test: update data: 10 // 组件进入活跃状态下更新数据 9 D/Test: resume
二、LiveData的优点
- 不需要手动控制生命周期。
- 不会因为Activity的停止,导致App崩溃。
- 数据状态始终保持最新。
- 不会产生内存泄漏。
三、LiveData Api
/** * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method. * * @param <T> The type of data hold by this instance */ @SuppressWarnings("WeakerAccess") public class MutableLiveData<T> extends LiveData<T> { /** * Creates a MutableLiveData initialized with the given {@code value}. * * @param value initial value */ public MutableLiveData(T value) { super(value); } /** * Creates a MutableLiveData with no value assigned to it. */ public MutableLiveData() { super(); } @Override public void postValue(T value) { super.postValue(value); } @Override public void setValue(T value) { super.setValue(value); } }
- 非UI线程使用postValue()方法。
- UI线程使用setValue()方法。
四、示例
RViewModel类:
class RViewModel : ViewModel() { val count: MutableLiveData<Int> = MutableLiveData() }
MainActivity类:
class MainActivity : AppCompatActivity() { private var _rViewModel: RViewModel? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) _rViewModel = ViewModelProvider(this).get(RViewModel::class.java) _rViewModel?.count?.observe(this, { countText.text = "$it" }) startTimer() } private fun startTimer() { Timer().schedule(object : TimerTask() { override fun run() { val count = (_rViewModel?.count?.value ?: 0) + 1 // UI线程使用setValue() // 非UI线程使用postValue() // timer task是子线程,所以使用postValue() _rViewModel?.count?.postValue(count) } }, 1000, 1000) } }