首页 > 解决方案 > 第二次未调用 RxJava Observable onNext

问题描述

我对 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 方法,它将一次性用品添加到复合一次性用品并在 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();
    }
}

标签: androidrx-javaretrofitgoogle-places-api

解决方案


推荐阅读