我对RxJava很陌生。最近,我一直在尝试实现一段代码,该代码使用Google Places Api检索所选半径范围内的地点及其ID的列表,然后使用之前检索的ID检索这些位置的详细信息。我在一个活动中有一个按钮,然后该按钮调用Api来检索信息。我的问题是,第一次单击该按钮时,将调用Api并发出数据。在连续尝试中,不会触发onNext,而只会调用onComplete。
这是我使用Retrofit检索地点列表及其详细信息的界面代码
@Headers("Content-Type: application/json")
@GET("api/place/nearbysearch/json?radius=5000&key="+API_KEY)
Observable<PlacesResponse> getPlaces(@Query("location") String location, @Query("types") String types);
@Headers("Content-Type: application/json")
@GET("api/place/details/json?key="+API_KEY)
Observable<PlacesDetailsResponse> getPlaceDetails(@Query("placeid") String placeId);
然后我用它来初始化我活动的onCreate方法上的Api
private void initiateApi() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.addConverterFactory(GsonConverterFactory.create())
.build();
mapService = retrofit.create(MapAPI.class);
}
我的活动中有一个搜索框和一个按钮。输入搜索查询并单击按钮后,我调用此方法首先检索用户的位置,然后获取地点的ID,最后获取这些地点的详细信息。
private void startPlaceFetchingTask(final String type) {
showProgress();
final long startTime = System.currentTimeMillis();
if (mResponses == null) {
mResponses = new ArrayList<>();
}
mResponses.clear();
Observable.fromCallable(this::getSynchronousLocation)
.subscribeOn(Schedulers.io())
.retryWhen(errors -> errors.flatMap(error -> {
long currentTime = System.currentTimeMillis();
if (error instanceof NullPointerException && (currentTime - startTime) < 30000) {
return Observable.timer(2, TimeUnit.SECONDS);
}
return Observable.error(error);
}))
.flatMap(location -> {
mLocation = location;
String locationString = location.latitude + "," + location.longitude;
return mapService.getPlaces(locationString, type)
.map(response -> response.getResults())
.flatMap(results -> Observable.fromIterable(results))
.flatMap(result -> mapService.getPlaceDetails(result.getPlaceId()));
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(getObserver());
}
这是我用来检索用户当前位置的
private LatLng getSynchronousLocation() throws SecurityException, ExecutionException, InterruptedException, TimeoutException {
Location location = Tasks.await(mFusedLocationClient.getLastLocation(), 30, TimeUnit.SECONDS);
return new LatLng(location.getLatitude(), location.getLongitude());
}
并获得观察者
private Observer<PlacesDetailsResponse> getObserver() {
return new Observer<PlacesDetailsResponse>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
}
@Override
public void onNext(PlacesDetailsResponse placesDetailsResponse) {
addPlace(placesDetailsResponse);
}
@Override
public void onError(Throwable e) {
//handle error
hideProgress();
}
@Override
public void onComplete() {
//do stuff
hideProgress();
}
};
正如我之前所说,在打开应用程序并首次单击搜索按钮时,所有这些都可以正常工作。如果再次单击该按钮,则只会调用onComplete,并且onNext上不会发射任何数据。 如果有人能指出我在做什么错,我将不胜感激。预先感谢。
编辑: 这是addDisposable方法,它将一次性对象添加到Composite一次性对象中,并在onDestroy期间进行处理。
private void addDisposable(Disposable disposable) {
if (mDisposable == null) {
mDisposable = new CompositeDisposable();
}
mDisposable.add(disposable);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mDisposable != null && !mDisposable.isDisposed()) {
mDisposable.dispose();
}
}