LiveEventBus icon indicating copy to clipboard operation
LiveEventBus copied to clipboard

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

Open kolyneh opened this issue 5 years ago • 9 comments

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

kolyneh avatar Mar 19 '19 01:03 kolyneh

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

budaowengd avatar Mar 19 '19 02:03 budaowengd

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

JeremyLiao avatar Mar 19 '19 06:03 JeremyLiao

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

budaowengd avatar Mar 31 '19 01:03 budaowengd

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

budaowengd avatar Mar 31 '19 01:03 budaowengd

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

budaowengd avatar Mar 31 '19 01:03 budaowengd

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

JeremyLiao avatar Mar 31 '19 03:03 JeremyLiao

   @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 的特性不一样了)

GeeJoe avatar Apr 15 '19 06:04 GeeJoe

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

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

JeremyLiao avatar Apr 15 '19 06:04 JeremyLiao

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

chenxi2035 avatar Dec 09 '20 08:12 chenxi2035