我的 Retrofit/ReactiveX 方法实际上是异步检索数据吗?
Does my Retrofit/ReactiveX method actually retrieve data asynchronously?
swipeRefreshLayout.setOnRefreshListener(() -> {
swipeRefreshLayout.setRefreshing(true);
retrieveData(mCardAdapter, db);
});
出于某种原因,以下方法阻塞了我的主 UI 线程,但它应该在后台 运行ning。比如我运行retrieveData()
时刷新指示器挂了。如果我在 运行ning 之前初始化进度对话框,它也会挂起并且我无法滚动浏览我的 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()
方法中将远程数据添加到本地数据存储可能是阻塞的原因,尽管我不确定。
您的网络调用是在您指定的新线程中完成的,但是订阅者方法 onNext()
和 onComplete()
在观察 Scheduler
上运行,这是主线程。
您似乎正在对它们执行一些数据库操作,请尝试使用 doOnNext()
运算符将缓存卸载到后台线程。
doOnNext()
会做的是,它会为您的流中的每个发射调用。
可以这样发展
service.getMedia()
.doOnNext(data -> cacheData(data))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
其中 cacheData(
) 是执行所有数据库调用的方法。 onNext()
和 onComplete()
中唯一剩下的就是更新 UI。
swipeRefreshLayout.setOnRefreshListener(() -> {
swipeRefreshLayout.setRefreshing(true);
retrieveData(mCardAdapter, db);
});
出于某种原因,以下方法阻塞了我的主 UI 线程,但它应该在后台 运行ning。比如我运行retrieveData()
时刷新指示器挂了。如果我在 运行ning 之前初始化进度对话框,它也会挂起并且我无法滚动浏览我的 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()
方法中将远程数据添加到本地数据存储可能是阻塞的原因,尽管我不确定。
您的网络调用是在您指定的新线程中完成的,但是订阅者方法 onNext()
和 onComplete()
在观察 Scheduler
上运行,这是主线程。
您似乎正在对它们执行一些数据库操作,请尝试使用 doOnNext()
运算符将缓存卸载到后台线程。
doOnNext()
会做的是,它会为您的流中的每个发射调用。
可以这样发展
service.getMedia()
.doOnNext(data -> cacheData(data))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
其中 cacheData(
) 是执行所有数据库调用的方法。 onNext()
和 onComplete()
中唯一剩下的就是更新 UI。