Open kolyneh opened 5 years ago
同问 ,这个问题怎么解决呢
带有LifecycleOwner参数的接口,如observe和observeSticky,是具有生命周期感知能力的,不用手动remove,会根据Owner的生命周期自动remove,observeForever接口注册的Observer,才需要用removeObserver手动删除。也就是说,observeForever和removeObserver是配对使用的。
谢谢,observeForever和removeObserver是配对使用的, 没错.
我现在遇到的问题是: 对ViewModel的LiveData进行重新的观察,导致之前的状态又发射了1-N次
googlesamples/android-architecture-components#63 google的策略是使用SingleLiveEvent: https://github.com/googlesamples/android-architecture/blob/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/SingleLiveEvent.java
我理解SingleLiveEvent和LiveEventBus要解决的问题是不一样的,我写了3个testcase:
@Test
public void testSingleLiveEvent1() throws Exception {
final Wrapper<String> wrapper = new Wrapper<>(null);
final SingleLiveEvent<String> singleLiveEvent = new SingleLiveEvent<>();
rule.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
singleLiveEvent.observe(rule.getActivity(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
wrapper.setTarget(s);
}
});
singleLiveEvent.setValue("value_test_sle");
}
});
Thread.sleep(500);
Assert.assertEquals(wrapper.getTarget(), "value_test_sle");
}
@Test
public void testSingleLiveEvent2() throws Exception {
final Wrapper<String> wrapper = new Wrapper<>(null);
final SingleLiveEvent<String> singleLiveEvent = new SingleLiveEvent<>();
rule.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
singleLiveEvent.setValue("value_test_sle");
singleLiveEvent.observe(rule.getActivity(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
wrapper.setTarget(s);
}
});
}
});
Thread.sleep(500);
Assert.assertEquals(wrapper.getTarget(), "value_test_sle");
}
@Test
public void testSingleLiveEvent3() throws Exception {
final Wrapper<String> wrapper1 = new Wrapper<>(null);
final Wrapper<String> wrapper2 = new Wrapper<>(null);
final SingleLiveEvent<String> singleLiveEvent = new SingleLiveEvent<>();
rule.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
singleLiveEvent.setValue("value_test_sle");
//第一个Observer能够收到消息
singleLiveEvent.observe(rule.getActivity(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
wrapper1.setTarget(s);
}
});
//第二个Observer收不到消息了
singleLiveEvent.observe(rule.getActivity(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
wrapper2.setTarget(s);
}
});
}
});
Thread.sleep(500);
Assert.assertEquals(wrapper1.getTarget(), "value_test_sle");
Assert.assertNull(wrapper2.getTarget());
}
test1和test2说明了在一般场景下,SingleLiveEvent和普通LiveData的效果是一致的,test3说明了SingleLiveEvent的应用场景,SingleLiveEvent调用setvalue之后,第一个Observer是收的到消息的,注册第二个Observer就收不到消息了。
这和LiveEventBus要解决的问题是不一致的,LiveEventBus要解决的是test2的场景,也就是先setvalue,然后注册的Observer都收不到消息。
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
super.observe(owner, new SafeCastObserver<>(observer));
}
每一次 observe 都 new 了一个新的 SafeCastObserver,所以如果多次 observe 之后,每一个 observer 都会受到消息,这应该是有问题的
并且如果规定 removeObserver 只能和 observeForever 配套使用的话,应该在文档中写清楚,不然很容易踩坑(因为这和 LiveData 的特性不一样了)
每一次 observe 都 new 了一个新的 SafeCastObserver,所以如果多次 observe 之后,每一个 observer 都会受到消息,这应该是有问题的
谢谢,我会在文档中强调这一点
@JeremyLiao 你好,在实践中我们需要随心所欲地removeObserver,因为有些observer是只需要执行一次的,这样更具有灵活性,期待大神早作修改,或许也可以提供一个参数,true的话无论何种情况,都删除此observer
使用observe接口添加的Observer,用removeObserver无法正确移除,后续还是会收到事件。 使用observeForever就没问题。