【问题标题】:I'm I affecting the values? or the references? Removing multiple Observers without a LifeCycleOwner我是在影响价值观吗?还是参考文献?在没有 LifeCycleOwner 的情况下删除多个观察者
【发布时间】:2020-10-15 03:27:54
【问题描述】:

我希望能够将不同的LiveData<X> 连接到同一个Observer。 到目前为止,我的小模块一直运行得非常好,但是为了避免将ViewModel 链接到LifecycleOwner,我提供了一种方法让模块在所有者为空时使用.observeForever() 函数,

观察者被包裹在一个更大的里面,它存储了一个int 值,该值声明每个 LiveData 上的 onChange() 是否是第一个......这样做是因为在某些情况下我需要忽略最初的 onChange() 回调。

因为可能有很多观察者(跟踪这个 int 值)...取决于 LiveData<X> 的数量(文档称它们为“来源”),我很容易清除所有观察者liveData.removeObservers(owner); 函数,自动清除该特定所有者的所有观察者。

但是由于所有者为空,现在我需要将所有观察者的引用保存在一个单一的中,并按名称删除它们liveData.removeObserver(observer);

我首先担心的是,通过在每次迭代中声明 new,我将永远失去对该观察者的引用。

如果是这种情况,我可以删除包装器中的观察者,正如预期的那样,所有观察者都是一样的,但首先想到的是,显而易见的事情是不要破坏最内在的观察者,但外在的观察者,因为这也会破坏内在的观察者。

问题是外面的不一样,而里面的却是普通的,所以:

我应该删除哪个,应该如何声明?

private RunTimeObserverWrapper<? super T> runTimeObserverWrapper;
/*This is the recent change I made in the hopes of being able to remove it/them */


private void connectObservers(
        List<LiveData<T>> liveDatas,
        boolean ignoreInitialization
) {


    this.listLiveData = liveDatas;

    Observer<? super T> itemObserver = itemObserverInitializer();
    /*This is the common observer*/


    for (LiveData<T> liveData: listLiveData
         ) {
        if (!liveData.hasObservers()) {

            runTimeObserverWrapper = new RunTimeObserverWrapper<>(ignoreInitialization, itemObserver);
            /*This is the recent change I made placing it as a field variable*/
            
//                RunTimeObserverWrapper<? super T> runTimeObserverWrapper = new RunTimeObserverWrapper<>(ignoreInitialization, itemObserver);
                /*This was working as intended, but I want to disassociate the module from the LifeCycleOwner*/


            if (owner != null) {
                liveData.observe(
                        owner,
                        runTimeObserverWrapper
                );
            } else {
                liveData.observeForever(
                        runTimeObserverWrapper
                );
            }
            /*New Snippet*/

//                liveData.observe(
//                        owner,
//                        runTimeObserverWrapper
//                );
                /*Old snippet*/

        }

    }
}

public void destroyObserversAndList() {

    for (LiveData<T> liveData: listLiveData
         ) {

//            liveData.removeObservers(owner);
            /*This was correctly removing ALL Observers*/
        
        if (owner != null) {
            liveData.removeObservers(owner);
        } else {
            liveData.removeObserver(runTimeObserverWrapper);
        }
        /*This is the new snippet to account for a lack of LifeCycleOwner*/
    }

    listLiveData.clear();
}

所以,如您所见,我担心的是,通过调用 liveData.removeObserver(runTimeObserverWrapper);,我只会删除迭代中由 new 定义的最后一个观察者。

我该怎么办?

【问题讨论】:

    标签: java android-lifecycle android-livedata observer-pattern


    【解决方案1】:

    解决方案比我最初意识到的要困难得多。 主要是因为通过解决次要的无关问题找到了答案:数据库有时会为表返回一个空值,其中所有行都被删除,并且我的列表不同模块,不知道它应该使用哪种类型的列表删除。

    这个问题的解决方案一次解决了两个问题,可能是第三个,其中一个就是上面提到的问题。

    解决方案是将两者都包装起来:LiveData 和它自己的观察者,现在应该给两者一个 Id,以便它的答案可以与它的 Id 一起存储在 LinkedHashMap 中。 如果答案为空,它只会存储空列表及其对应的 Id,并删除之前的值。

    现在 LiveData 已与它自己的 Observer 捆绑在一起,我可以创建一个可以从它自己的 Observer 中释放它的方法,并且通过遍历每个 LiveDataWrapper,我可以调用这个方法并删除它们。

    public void destroyObserversAndList() {
    
        if (listLiveData != null) {
            for (LiveDataSourceWrapper<T> liveData: listLiveData
            ) {
    
                liveData.removeObserver();
    
            }
            listLiveData.clear();
    
    
        }
    
    }
    

    还有 LiveDataSourceWrapper 类:

    public class LiveDataSourceWrapper<X> {
    
        private int liveDataId;
        private SourceObserverWrapper<X> identityLiveDataObserver;
        private LiveData<X> liveData;
    
    
        public LiveDataSourceWrapper(
                LiveData<X> liveData,
                int liveDataId
        ) {
            this.liveData = liveData;
            this.liveDataId = liveDataId;
        }
    
        public void observeForever(@NonNull SourceObserver<X> observer) {
    
            identityLiveDataObserver = new SourceObserverWrapper<X>(liveDataId, observer);
            liveData.observeForever(identityLiveDataObserver);
    
        }
    
        public void removeObserver() {
            liveData.removeObserver(identityLiveDataObserver);
    
    
        }
    
    
        public boolean hasObservers() {
            return liveData.hasObservers();
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 2017-03-13
      • 2016-02-11
      • 2011-06-17
      相关资源
      最近更新 更多