2

我知道这是一个复杂的问题,如果不发布数百行代码就无法给出明确的答案,这就是我通过一般想法和指针寻求帮助的原因。

我有一个 Room@Query返回一个 RxJava3 Flowable<List<...>>,我在 RxJava 线程上订阅了它,并从RxJava 线程上Schedulers.io()的活动范围内观察。然后将数据存储在我的 ViewModel as中,在处理 Android 组件的生命周期时,它比 RxJava 表现得更好。ViewModelAndroidSchedulers.mainThread()LiveData

这个想法是有一个干净和即时的数据更新模式,不必在每个活动或片段生命周期事件(例如onPausedand )上分别处理处置和重新订阅onResumed,并且即使我的活动被隐藏也可以在后台更新以便在返回我的活动时避免可怕的刷新滞后。我对这种设计模式感到非常惊讶。我仍然是,但我开始怀疑。

List<...>当使用相同的设计模式启动另一个活动时,我确实更改了一个值并立即从另一个获取更新ViewModel。不同Activity的,不同ViewModel的,相同的设计,相同的数据库表。返回第一个Activity时,我发现新数据永远不会更新:即使数据集发生了变化,Room 也没有发出任何更新。我必须再次处理和订阅才能看到新数据。

所以我的问题是:关于我的问题的根源可能在哪里的任何指针?!这种设计模式的核心是不是有些烂掉了?我误解了所有这些东西应该一起工作吗?由于某些线程问题,这只是我的错误吗?或者我应该为 Room 填写错误报告?

ViewModel我试图从我的第一个观察另一个非 Room RxJava3 观察Activity,并且当它的数据集更新时它确实得到更新。

顺便说一句,我还使用 Hilt 将所有内容注入为@Singleton.

感谢您的时间 :-)

4

1 回答 1

0

经过一周的头痛,我终于偶然发现了一个解决方案,它恰好是干净和优雅的。

问题是 RxJava,我刚刚了解到,它不应该无缝处理对同一个Observable. 据说解决方案是使用publish(), connect(),refcount()运算符,或者更好地使用快捷方式share()。我尝试了所有我能想到的方法,但没有成功(实际上它让情况变得更糟)。我还尝试从我的存储库subscribe()到 RoomFlowable并通过BehaviorSubject.

Room 的文档中有这种奇怪的东西org.reactivestreams.Publisher,我不知道它的附加价值,而且它的起源甚至不是我熟悉的io.reactivex.rxjava3. 事实证明这是解决方案。编辑:原来Publisher是一个Flowable碰巧实现的接口。

构建.gradle

implementation 'android.arch.lifecycle:reactivestreams:+'

道.java

@Query("...")
Flowable<List<...>> getFlowable();

ViewModel.java

public liveData;

@Inject
public ViewModel(@NonNull RoomDatabase roomDatabase) {
    liveData = LiveDataReactiveStreams.fromPublisher(roomDatabase.dao().getFlowable());
}

这似乎太容易成为现实,但据我所知,这种方式似乎工作 更好

编辑: 事实证明,这个问题的根源比我想象的要恶毒一点。我认为@InstallIn(SingletonComponent.class)在我的依赖注入@Module中就足够了,但显然还需要@Singleton对每个方法进行注释。@Provides

@Module
@InstallIn(SingletonComponent.class)
public abstract class DependencyInjection
{
    @Provides
    @NonNull
    @Singleton // do not omit this
    public static DataDao provideDataDao(@NonNull RoomDatabase roomDatabase) {
        return roomDatabase.dataDao();
    }

    @Provides
    @NonNull
    @Singleton // do not omit this
    public static RoomDatabase provideRoomDatabase(@ApplicationContext Context applicationContext) {
        return
                BuildConfig.DEBUG ?
                        Room.databaseBuilder(applicationContext, RoomDatabase.class, "playground.db").fallbackToDestructiveMigration().build() :
                        Room.databaseBuilder(applicationContext, RoomDatabase.class, "playground.db").build() ;
    }
}
于 2021-03-10T12:13:52.797 回答