2017-02-21 7 views
0

我现在正在研究一个任务,它将从网络中获取数据,在UI上显示并将数据保存到本地数据库以供以后使用。目前,我做如下:从网络加载,在用户界面上显示,并通过RxJava保存到磁盘

//Cloud loading 
Observable<MyModel> loadDataFromCloud(); 

//Database 
Observable<MyModel> saveDataToDisk(MyModel myModel); 

//Load data 
loadDataFromCloud() 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .flatMap(new Func1<MyModel, Observable<MyModel>>() { 
    @Override 
    public Observable<MyModel> call(MyModel myModel) { 
     return saveDataToDisk(myModel); 
    } 
    }) 
    .subscribe(new Subscriber<MyModel>() { 
    @Override 
    public void onCompleted() { 

    } 

    @Override 
    public void onError(Throwable e) { 
     //exception handling 
    } 

    @Override 
    public void onNext(MyModel myModel) { 
     //bind myModel to UI 
    } 
    }); 

这种方法工作得很好,但由于数据模型变得更加复杂和数据库越来越大,它的效率不高了,因为所有的数据库事务,现在在主执行线程和用户界面需要等到事务完成才能获得数据。

我现在改变这种新的方法:

//A Singleton 
Scheduler scheduler = Schedulers.from(Executors.newSingleThreadExecutor()); 

//Load data 
loadDataFromCloud() 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .flatMap(new Func1<MyModel, Observable<MyModel>>() { 
    @Override 
    public Observable<MyModel> call(MyModel myModel) { 
     try { 
     //bind myModel to UI 
     return Observable.just(s); 
     } catch(Exception e) { 
     return Observable.error(e) 
     } 
    } 
    }) 
    .observeOn(scheduler) 
    .flatMap(new Func1<MyModel, Observable<MyModel>>() { 
    @Override 
    public Observable<MyModel> call(MyModel myModel) { 
     return saveDataToDisk(myModel); 
    } 
    }) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(new Subscriber<MyModel>() { 
    @Override 
    public void onCompleted() { 

    } 

    @Override 
    public void onError(Throwable e) { 
     //exception handling 
    } 

    @Override 
    public void onNext(MyModel myModel) { 
     //do nothing 
    } 
    }); 

我使用Schedulers.from(Executors.newSingleThreadExecutor()),以确保所有的数据库事务将是线程安全的。

而且我有一些问题:

  1. 是否使用Schedulers.from(Executors.newSingleThreadExecutor()),以确保所有的数据库事务将是线程安全的正确方法是?
  2. 有没有更好的方式来实现这一目标,自上次onNext()只是在做什么,似乎是不明智
  3. 随着RxJava可以在我们开始做两个任务,同时在两个不同的线程(显示在用户界面和保存到磁盘)

我搜索了一段时间,并得到了一些文章,如this one,但他们并没有直接去我的问题。

回答

1

首先,首先,你是在主线程上进行IO操作,这是一个糟糕的做法,在android中它可能会导致anr。

  1. 基本上应该同步,但只要您使用在您的应用程序相同的Scheduler,否则您将创建新的线程为每个订阅此观察到。但是,这样做有点奇怪,因为DB操作通常是线程安全的。
  2. 在你的场景中,你想要显示UI和saveDataToDisk()而不用等待,所以你可以使用doOnNext运算符来启动对不同观测值的保存操作(你不关心其结果),而没有观察它的结果。

所以总结起来,你应该是这样的:

loadDataFromCloud() 
    .doOnNext(data - > saveDataToDisk().subscribeOn(Schedulers.io())) 
    .subscribeOn(Schedulers.io()) 
    .observeOn(AndroidSchedulers.mainThread()) 
    .subscribe(data -> //uodate your ui) 

丹卢帖子是一个很好的例子,你应该遵循的例子在那里。

+0

谢谢@yosriz,'.doOnNext(data - > saveDataToDisk()。subscribeOn(Schedulers.io()))'完全做到了这一招 –

相关问题