我的Retrofit / ReactiveX方法是否实际异步检索数据?

时间:2017-12-22 22:15:25

标签: java android rest retrofit reactivex

swipeRefreshLayout.setOnRefreshListener(() -> {
 swipeRefreshLayout.setRefreshing(true);
 retrieveData(mCardAdapter, db);
});

由于某种原因,以下方法阻止了我的主UI线程,但它应该在后台运行。例如,当我运行retrieveData()时,刷新指示器会挂起。如果我在运行之前初始化进度对话框,它也会挂起,我无法滚动我的RecyclerView。我从根本上误解了一些事情吗?

public void retrieveData(final CardAdapter mCardAdapter, SQLiteHelper db) {
 CausticRetrofitService service = ServiceFactory.createRetrofitService(CausticRetrofitService.class, CausticRetrofitService.SERVICE_ENDPOINT);
 service.getMedia()
  .subscribeOn(Schedulers.newThread())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Subscriber < MediaResponse > () {
   @Override
   public final void onCompleted() {

    Log.e("CausticRetrofitService", "Caustic Request Completed!");

    /* Cancel all progress indicators after data retrieval complete */
    setRefreshingFalse();

    // TODO: Add media to local data store and then display them one-by-one in real-time
    mCardAdapter.addData(db.getAllMediaImages()); // Add all media images to card views
    Log.d(getClass().toString(), "Added to local database: " + db.getAllMediaImages());
    mCardAdapter.notifyDataSetChanged();
   }

   @Override
   public final void onError(Throwable e) {
    /* Cancel all progress indicators on data retrieval error */
    setRefreshingFalse();

    Toast.makeText(getApplicationContext(), "Cannot retrieve data. Please try again later.", Toast.LENGTH_SHORT).show();
    Log.e("CausticRetrofitService", e.getMessage());
   }

   @Override
   public final void onNext(MediaResponse mediaResponse) {
    if (mediaResponse != null) {

     Log.e("CausticRetrofitService", "Returned objects: " + mediaResponse.getResults());

     for (String mediaId: mediaResponse.getResults()) {
      Log.e("CausticRetrofitService", mediaId);
     }

     List < String > mediaIds = mediaResponse.getResults();
     Log.d(getClass().toString(), "All Media IDs: " + mediaIds);

     if (mediaIds.isEmpty()) {
      Toast.makeText(getApplicationContext(), "Cannot retrieve data. Please try again later.", Toast.LENGTH_SHORT).show();
     }

     mCardAdapter.clear();
     mCardAdapter.notifyDataSetChanged();

     /* Store objects from remote web service to local database */
     for (String mediaId: mediaIds) {
      // TODO: Why are these null?
      Log.d(getClass().toString(), "Media Id: " + mediaId);
      MediaImage newMediaImage = new MediaImage();
      newMediaImage.setTitle(mediaId);
      db.addMediaImage(newMediaImage); // Add media image to local database
     }

    } else {
     Log.e("CausticRetrofitService", "Object returned is null.");
    }

   }

  });
}

我认为在onNext()方法中将远程数据添加到本地数据存储可能会阻塞,但我不确定。

1 个答案:

答案 0 :(得分:1)

您的网络调用是在您指定的新线程中完成的,但订阅者方法onNext()onComplete()在观察Scheduler上运行,这是主线程。

您似乎正在对这些操作进行一些数据库操作,尝试使用doOnNext()运算符将缓存卸载到后台线程。

doOnNext()会做什么,就是为你的流中的每个发射调用它。

它可以像这样

service.getMedia()
  .doOnNext(data -> cacheData(data))
  .subscribeOn(Schedulers.newThread())
  .observeOn(AndroidSchedulers.mainThread())

其中cacheData()是执行所有数据库调用的方法。而onNext()onComplete()中剩下的唯一内容就是仅更新用户界面。