JeremyLiao / LiveEventBus

:mailbox_with_mail:EventBus for Android,消息总线,基于LiveData,具有生命周期感知能力,支持Sticky,支持AndroidX,支持跨进程,支持跨APP
Apache License 2.0
3.89k stars 541 forks source link

使用observe接口添加的Observer,用removeObserver无法正确移除 #27

Open kolyneh opened 5 years ago

kolyneh commented 5 years ago

使用observe接口添加的Observer,用removeObserver无法正确移除,后续还是会收到事件。 使用observeForever就没问题。

budaowengd commented 5 years ago

同问 ,这个问题怎么解决呢

JeremyLiao commented 5 years ago

带有LifecycleOwner参数的接口,如observe和observeSticky,是具有生命周期感知能力的,不用手动remove,会根据Owner的生命周期自动remove,observeForever接口注册的Observer,才需要用removeObserver手动删除。也就是说,observeForever和removeObserver是配对使用的。

budaowengd commented 5 years ago

谢谢,observeForever和removeObserver是配对使用的, 没错.

budaowengd commented 5 years ago

我现在遇到的问题是: 对ViewModel的LiveData进行重新的观察,导致之前的状态又发射了1-N次

budaowengd commented 5 years ago

https://github.com/googlesamples/android-architecture-components/issues/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

JeremyLiao commented 5 years ago

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都收不到消息。

GeeJoe commented 5 years ago
   @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 的特性不一样了)

JeremyLiao commented 5 years ago

每一次 observe 都 new 了一个新的 SafeCastObserver,所以如果多次 observe 之后,每一个 observer 都会受到消息,这应该是有问题的

谢谢,我会在文档中强调这一点

chenxi2035 commented 3 years ago

@JeremyLiao 你好,在实践中我们需要随心所欲地removeObserver,因为有些observer是只需要执行一次的,这样更具有灵活性,期待大神早作修改,或许也可以提供一个参数,true的话无论何种情况,都删除此observer