【问题标题】:How do you structure a local data source using RxJava and Realm?如何使用 RxJava 和 Realm 构建本地数据源?
【发布时间】:2017-11-07 01:36:47
【问题描述】:

Realm 现在支持引入了 asFlowable 功能的 RxJava 2,我感到非常兴奋,因此感谢为此做出贡献的任何人。

我面临的问题是如何在我的本地数据源单例类中最好地管理领域实例的生命周期。我的本地数据源类似于Android架构示例here。在 RxJava 的 Realm 示例中,他们在 onCreate 中实例化一个领域实例,并在活动的 onDestroy 中关闭它。但是,由于我的本地数据源是单例,我不会有这些生命周期事件来实例化和关闭实例。

问题是:我应该在每次创建单例时实例化一个领域实例并仅在单例被销毁时关闭它,还是应该在活动/片段中实例化一个领域实例,将其注入本地数据源,并且然后在活动/片段中关闭它? 欢迎任何其他建议。谢谢!

【问题讨论】:

    标签: android realm mvp rx-java2


    【解决方案1】:

    他们在 onCreate 中实例化一个领域实例并在活动的 onDestroy 中关闭它

    这是针对 UI 线程 Realm 的。

    将其注入本地数据源

    您收到的Realm 实例是线程本地引用计数实例,而不是“线程安全”单例。所以你可能不应该直接注入Realm,因为那样它将被限制在一个给定的线程中。


    一般UI线程Realm可以由ViewModelretained fragmentonCreate()/onDestroy()等来管理,因为Realm只有在RealmResults有效时才提供通知,这意味着Realm实例是打开的。

    因此,要在任何线程上公开 RealmResults,不知道它是 RealmResults 的事实,您需要这样做

    public Flowable<List<ChatsModel>> getAllChatsData(Realm realm) {
        RealmQuery<ChatsModel> query = realm.where(ChatsModel.class);
        if(realm.isAutoRefresh()) {
            return query.findAllAsync().asFlowable().filter(RealmResults::isLoaded);
        } else {
            return Flowable.just(query.findAll());
        } 
    }
    

    如您所见,它接收Realm 实例作为其输入。现在,如果您想删除该参数,则需要在从本地数据源公开的任何内容中隐藏引用计数,我个人认为 LiveData 是最好的选择 - 因为它有 @987654330 @/onInactive() 回调。

    public class RealmLiveData<T extends RealmModel> extends MutableLiveData<List<T>> {
        public interface QueryDefinition<M extends RealmModel> {
            RealmResults<M> createResults(Realm realm);
        }
    
        private final QueryDefinition<T> queryDefinition;
    
        public RealmLiveData(QueryDefinition<T> query) {
            this.queryDefinition = query;
            // TODO: handle realm config other than DefaultConfig if needed
        }
    
        Realm realm;
        RealmResults<T> results;
        RealmChangeListener<RealmResults<T>> realmChangeListener = new RealmChangeListener<RealmResults<T>>() {
            @Override
            public void onChange(RealmResults<T> results) {
                if(results.isLoaded()) {
                    setValue(results);
                }
            }
        }
    
        @Override
        public void onActive() {
            realm = Realm.getDefaultInstance();
            results = queryDefinition.createResults(realm);
            results.addChangeListener(realmChangeListener);
        }
    
        @Override
        public void onInactive() {
            setValue(Collections.emptyList());
            results.removeChangeListener(realmChangeListener);
            realm.close();
            realm = null;
        }
    }
    

    然后你可以公开一个 LiveData:

    public class MyDao {
        public LiveData<List<MyObject>> findMyObjectsWithChanges() {
            return new RealmLiveData<MyObject>(new QueryDefinition<MyObject>() {
                 @Override
                 public RealmResults<MyObject> createResults(Realm realm) {
                     return realm.where(MyObject).findAllAsync();
                 }
            });
        }
    }
    

    Lambda 表达式让它变得更好

    public class MyDao {
        public LiveData<List<MyObject>> findMyObjectsWithChanges() {
            return new RealmLiveData<MyObject>((realm) -> realm.where(MyObject.class).findAllAsync());
        }
    }
    

    所以这是一个值得研究的可能性。

    【讨论】:

      【解决方案2】:

      注意,不关闭 UI 线程上的 Realm 文件并不一定是危险的,因为它会自动保持最新。唯一的缺点是您不能再使用需要完全关闭文件的功能,例如删除它。

      就我个人而言,我认为生命周期事件确实属于模型层,因为您经常需要它们用于控制传感器和/或 GPS 等其他事情。

      特别是现在架构组件已经达到 1.0,我建议将 LifecycleObservable 作为控制领域实例的手段:https://developer.android.com/topic/libraries/architecture/lifecycle.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多