Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 安卓领域+;RxJava-从错误线程进行领域访问。领域对象只能在创建它们的线程上访问_Android_Multithreading_Realm_Rx Java - Fatal编程技术网

Android 安卓领域+;RxJava-从错误线程进行领域访问。领域对象只能在创建它们的线程上访问

Android 安卓领域+;RxJava-从错误线程进行领域访问。领域对象只能在创建它们的线程上访问,android,multithreading,realm,rx-java,Android,Multithreading,Realm,Rx Java,我正在尝试实现RxJava+领域+改造+存储库模式 以下是我的本地实现: @Override public Observable<Page> search(@NonNull final String query) { return Realm.getDefaultInstance().where(Page.class) .equalTo("query", query) .findAll()

我正在尝试实现RxJava+领域+改造+存储库模式

以下是我的本地实现:

@Override
public Observable<Page> search(@NonNull final String query) {

        return Realm.getDefaultInstance().where(Page.class)
                .equalTo("query", query)
                .findAll()
                .asObservable()
                .cast(Page.class);
    }
 @Override
 public Observable<Page> search(@NonNull String query) {
        return mWikiServices.search(query).map(new Func1<Result, Page>() {
            @Override
            public Page call(Result result) {
                final List<Page> pages = new ArrayList<>(result.getQuery().getPages().values());
                return pages.get(0);
            }
        });
    }
 final Observable<Page> localResult = mSearchLocalDataSource.search(query);
 final Observable<Page> remoteResult = mSearchRemoteDataSource.search(query)
                .doOnNext(new Action1<Page>() {
                    @Override
                    public void call(Page page) {
                        //mSearchLocalDataSource.save(query, page);
                        //mResultCache.put(query, page);
                    }
                });

        return Observable.concat(localResult, remoteResult)
                .first()
                .doOnError(new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        throwable.printStackTrace();
                    }
                });
@Override
public Observable<Page> search(@NonNull String query) {
        return mWikiServices.search(query).flatMap(new Func1<Result, Observable<Page>>() {
            @Override
            public Observable<Page> call(Result result) {
                final ArrayList<Page> pages = new ArrayList<>(result.getQuery().getPages().values());
                Log.i("data from", "remote");
                return Observable.from(pages).first();
            }
        });
    }
@Override
public Observable<Page> search(@NonNull final String query) {
        return Observable.create(new Observable.OnSubscribe<Page>() {
            @Override
            public void call(Subscriber<? super Page> subscriber) {
                final Realm realm = Realm.getInstance(mRealmConfiguration);
                final Page page = realm.where(Page.class)
                        .equalTo("query", query)
                        .findFirst();
                if (page != null && page.isLoaded() && page.isValid()) {
                    Log.i("data from", "realm");
                    subscriber.onNext(realm.copyFromRealm(page));
                } else {
                    Observable.empty();
                }
                subscriber.onCompleted();
                realm.close();
            }
        });
    }
@覆盖
公共可观察搜索(@NonNull final String query){
返回Realm.getDefaultInstance().where(Page.class)
.equalTo(“查询”,查询)
.findAll()
.asObservable()
.cast(Page.class);
}
以下是我的远程实现:

@Override
public Observable<Page> search(@NonNull final String query) {

        return Realm.getDefaultInstance().where(Page.class)
                .equalTo("query", query)
                .findAll()
                .asObservable()
                .cast(Page.class);
    }
 @Override
 public Observable<Page> search(@NonNull String query) {
        return mWikiServices.search(query).map(new Func1<Result, Page>() {
            @Override
            public Page call(Result result) {
                final List<Page> pages = new ArrayList<>(result.getQuery().getPages().values());
                return pages.get(0);
            }
        });
    }
 final Observable<Page> localResult = mSearchLocalDataSource.search(query);
 final Observable<Page> remoteResult = mSearchRemoteDataSource.search(query)
                .doOnNext(new Action1<Page>() {
                    @Override
                    public void call(Page page) {
                        //mSearchLocalDataSource.save(query, page);
                        //mResultCache.put(query, page);
                    }
                });

        return Observable.concat(localResult, remoteResult)
                .first()
                .doOnError(new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        throwable.printStackTrace();
                    }
                });
@Override
public Observable<Page> search(@NonNull String query) {
        return mWikiServices.search(query).flatMap(new Func1<Result, Observable<Page>>() {
            @Override
            public Observable<Page> call(Result result) {
                final ArrayList<Page> pages = new ArrayList<>(result.getQuery().getPages().values());
                Log.i("data from", "remote");
                return Observable.from(pages).first();
            }
        });
    }
@Override
public Observable<Page> search(@NonNull final String query) {
        return Observable.create(new Observable.OnSubscribe<Page>() {
            @Override
            public void call(Subscriber<? super Page> subscriber) {
                final Realm realm = Realm.getInstance(mRealmConfiguration);
                final Page page = realm.where(Page.class)
                        .equalTo("query", query)
                        .findFirst();
                if (page != null && page.isLoaded() && page.isValid()) {
                    Log.i("data from", "realm");
                    subscriber.onNext(realm.copyFromRealm(page));
                } else {
                    Observable.empty();
                }
                subscriber.onCompleted();
                realm.close();
            }
        });
    }
@覆盖
公共可观察搜索(@NonNull字符串查询){
返回mWikiServices.search(query.map)(new Func1(){
@凌驾
公共页面调用(结果){
最终列表页=新的ArrayList(result.getQuery().getPages().values());
返回页面。获取(0);
}
});
}
以下是我的回购实施:

@Override
public Observable<Page> search(@NonNull final String query) {

        return Realm.getDefaultInstance().where(Page.class)
                .equalTo("query", query)
                .findAll()
                .asObservable()
                .cast(Page.class);
    }
 @Override
 public Observable<Page> search(@NonNull String query) {
        return mWikiServices.search(query).map(new Func1<Result, Page>() {
            @Override
            public Page call(Result result) {
                final List<Page> pages = new ArrayList<>(result.getQuery().getPages().values());
                return pages.get(0);
            }
        });
    }
 final Observable<Page> localResult = mSearchLocalDataSource.search(query);
 final Observable<Page> remoteResult = mSearchRemoteDataSource.search(query)
                .doOnNext(new Action1<Page>() {
                    @Override
                    public void call(Page page) {
                        //mSearchLocalDataSource.save(query, page);
                        //mResultCache.put(query, page);
                    }
                });

        return Observable.concat(localResult, remoteResult)
                .first()
                .doOnError(new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        throwable.printStackTrace();
                    }
                });
@Override
public Observable<Page> search(@NonNull String query) {
        return mWikiServices.search(query).flatMap(new Func1<Result, Observable<Page>>() {
            @Override
            public Observable<Page> call(Result result) {
                final ArrayList<Page> pages = new ArrayList<>(result.getQuery().getPages().values());
                Log.i("data from", "remote");
                return Observable.from(pages).first();
            }
        });
    }
@Override
public Observable<Page> search(@NonNull final String query) {
        return Observable.create(new Observable.OnSubscribe<Page>() {
            @Override
            public void call(Subscriber<? super Page> subscriber) {
                final Realm realm = Realm.getInstance(mRealmConfiguration);
                final Page page = realm.where(Page.class)
                        .equalTo("query", query)
                        .findFirst();
                if (page != null && page.isLoaded() && page.isValid()) {
                    Log.i("data from", "realm");
                    subscriber.onNext(realm.copyFromRealm(page));
                } else {
                    Observable.empty();
                }
                subscriber.onCompleted();
                realm.close();
            }
        });
    }
final Observable localResult=mSearchLocalDataSource.search(查询);
最终可观察的remoteResult=mSearchRemoteDataSource.search(查询)
.doOnNext(新行动1){
@凌驾
公共作废调用(第页){
//mSearchLocalDataSource.save(查询,页面);
//mResultCache.put(查询,页面);
}
});
返回Observable.concat(localResult、remoteResult)
.first()
.doon错误(新操作1(){
@凌驾
公共无效呼叫(可丢弃可丢弃){
printStackTrace();
}
});
最后是我在presenter中的订阅

final Subscription subscription = mSearchRepository.search(this.mQuery)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Page>() {
                    @Override
                    public void onCompleted() {
                        // Completed
                    }

                    @Override
                    public void onError(Throwable e) {
                        mView.onDefaultMessage(e.getMessage());
                    }

                    @Override
                    public void onNext(Page page) {
                        mView.onDefaultMessage(page.getContent());
                    }
                });

        mCompositeSubscription.add(subscription);
final Subscription Subscription=mSearchRepository.search(this.mQuery)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.订阅(新观察员){
@凌驾
未完成的公共无效(){
//完成
}
@凌驾
公共无效申报人(可丢弃的e){
mView.onDefaultMessage(e.getMessage());
}
@凌驾
公共void onNext(第页){
mView.onDefaultMessage(page.getContent());
}
});
mcompositionsubscription.add(订阅);
当我运行代码时,我得到这个异常:来自错误线程的领域访问。领域对象只能在创建它们的线程上访问

我在Github repo领域尝试了官方解决方案,但没有一个有效。仍然得到这个例外

我想我得到这个异常是因为我订阅了一个io线程。在主线程中创建领域实例。所以我得到了这个例外

是否有任何实施方案


谢谢。

上次编辑:从技术上讲,这两种解决方案都有效,正如Viraj Tank所说的-vs

不过,正确的深度集成方法应该是从服务中单独下载,并有一个用户监听底层领域中的更改。(
realmResults.asObservable().subscribe()



老实说,我忍不住觉得这在概念上是有缺陷的

首先,领域查询在创建时在主线程上执行

@Override
public Observable<Page> search(@NonNull final String query) {

        return Realm.getDefaultInstance().where(Page.class)

考虑到您似乎不依赖于领域的自动更新功能,您可以考虑使用<代码> Value.CopyOfEngEngEy(ObjixObjix:ObjixObj/Objy>)来创建一个可以在线程之间传递的非托管副本。


但实际上,为了正确地使用领域,您应该有两个订阅-从网络到领域的单个数据流;还有一个订阅
RealmResults.asObservable()
,当网页被网络observable写入到下面时,它会通知你,这就是我们的想法

。因此,如果在RecyclerView中显示多个元素,则甚至不需要可观察的领域,因为
RealmRecylerViewAdapter
通过
RealmChangeListener
管理其自动更新,而无需依赖
asObservable()
来完成



编辑:

在分叉之后,显然我一直都是对的。简单的零拷贝解决方案是为本地可观察对象添加
subscribeOn(AndroidSchedulers.mainThread())

令人惊讶的是,变化不大

    final Observable<Page> localResult = mSearchLocalDataSource.search(query).filter(new Func1<Page, Boolean>() {
        @Override
        public Boolean call(Page page) {
            return page != null;
        }
    }).subscribeOn(AndroidSchedulers.mainThread());
    final Observable<Page> remoteResult = mSearchRemoteDataSource.search(query).subscribeOn(Schedulers.io())
            .doOnNext(new Action1<Page>() {
                @Override
                public void call(Page page) {
                    if (page != null) {
                        mSearchLocalDataSource.save(query, page);
                      //  mResultCache.put(query, page);
                    }
                }
            });


    return Observable.concat(localResult, remoteResult)
            .first()
            .map(new Func1<Page, Page>() {
                @Override
                public Page call(Page page) {
                    if (page == null) {
                        throw new NoSuchElementException("No result found!");
                    }
                    return page;
                }
            });
应替换为以下内容:

@Override
public Observable<Page> search(@NonNull final String query) {
    Realm realm = mRealmManager.getRealm(); // UI thread only!
    final Page page = realm.where(Page.class).equalTo("query", query).findFirst();
    if(page != null) {
        Log.i("data from", "realm");
        return page.asObservable();
    } else {
        Log.i("data is", "empty");
        return Observable.empty();
    }
}
@覆盖
公共可观察搜索(@NonNull final String query){
Realm Realm=mRealmManager.getRealm();//仅限UI线程!
最后一页Page=realm.where(Page.class).equalTo(“query”,query).findFirst();
如果(第页!=null){
Log.i(“来自”、“领域”的数据);
返回页面.asObservable();
}否则{
Log.i(“数据为”、“空”);
return-Observable.empty();
}
}

最后,一些额外的架构设计可以让这一切变得更好,但我想我还是睡一觉吧。

最后一次编辑:从技术上讲,这两种解决方案都有效,正如Viraj Tank所说的-vs

不过,正确的深度集成方法应该是从服务中单独下载,并有一个用户监听底层领域中的更改。(
realmResults.asObservable().subscribe()



老实说,我忍不住觉得这在概念上是有缺陷的

首先,领域查询在创建时在主线程上执行

@Override
public Observable<Page> search(@NonNull final String query) {

        return Realm.getDefaultInstance().where(Page.class)

考虑到您似乎不依赖于领域的自动更新功能,您可以考虑使用<代码> Value.CopyOfEngEngEy(ObjixObjix:ObjixObj/Objy>)来创建一个可以在线程之间传递的非托管副本。


但实际上,为了正确使用领域,您应该有两个订阅-一个dat