等待 Retrofit 2 异步调用的响应

Wait for response from Retrofit 2 asynchronous call

在我的 Android 中 activity 我有一个异步调用 google 映射 API 在一个方法中看到下面的代码:

public void reverseGeocode(String lat, String lng) {

        String geocodeApiUrl = getUrl(lat, lng);
        GoogleService googleService = GoogleServiceBuilder.buildService(GoogleService.class);
        Call<Address> geocodeRequest = googleService.geocodeAddress(geocodeApiUrl);


        geocodeRequest.enqueue(new Callback<Address>() {
            @Override
            public void onResponse(Call<Address> call, Response<Address> response) {

                if (response.errorBody() == null) {
                    if (response.body().getResults().length > 0) {
                        if (response.body().getResults()[0].getFormatted_address() != null) {
                            dropOffAddress = response.body().getResults()[0].getFormatted_address();
                        }


                    }

                } else {
                    Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<Address> call, Throwable t) {
                Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
            }
        });

    }

此方法在 Google 地图标记的 onMarkerDragEnd 回调函数中调用,请参见下面的代码:

@Override
            public void onMarkerDragEnd(Marker marker) {

                double lat = marker.getPosition().latitude;
                double lng = marker.getPosition().longitude;
                reverseGeocode(String.valueOf(lat), String.valueOf(lng));
                marker.setSnippet(dropOffAddress);
                marker.showInfoWindow();
                editor.putString("dropOffAddress", dropOffAddress);
                editor.putString("lat", String.valueOf(lat));
                editor.putString("lng", String.valueOf(lng));
                editor.apply();
            }

这里的问题是我第一次移动标记时调用了 reverseGeocode 方法但没有等待 onMarkerDragEnd继续执行并将 null 放入 dropOffAddress 变量的值中,该变量旨在显示在标记的片段中。

我的问题是如何在继续执行之前等待 reverseGeocode 方法在 onMarkerDragEnd 中的响应?

谢谢。

您可以使用 java.utils.Concurrent class 中的 CountDownLatch。 这是一个例子:

public class DoSomething {
    private Address dropoffAddr;
    private CountDownLatch dropoffAddrLatch = new CountDownLatch(1);

    public void getAddressCallback(Address addr) {
        dropoffAddr = addr;
        dropoffAddrLatch.countDown();
    }

    @Override
    public void onMarkerDragEnd(Marker marker) {
        //your stuff
        reverseGeocode(...); //you should call getAddressCallback once you have everything
        dropOffAddrLatch.await(); //this will wait until getAddressCallBack has returned,
                                  // you can call dropoffAddrLatch.countDown() wherever you want.
        //finish your stuff
    }
}

唯一的就是你。需要的是标记,只需将其作为参数传递给你的改造 api 调用类似这样的东西。

public void reverseGeocode(String lat, String lng, Marker marker) {

    String geocodeApiUrl = getUrl(lat, lng);
    GoogleService googleService = GoogleServiceBuilder.buildService(GoogleService.class);
    Call<Address> geocodeRequest = googleService.geocodeAddress(geocodeApiUrl);


    geocodeRequest.enqueue(new Callback<Address>() {
        @Override
        public void onResponse(Call<Address> call, Response<Address> response) {

            if (response.errorBody() == null) {
                if (response.body().getResults().length > 0) {
                    if (response.body().getResults()[0].getFormatted_address() != null) {
                        dropOffAddress = response.body().getResults()[0].getFormatted_address();
                         applyGeoCode(marker)
                    }


                }

            } else {
                Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<Address> call, Throwable t) {
            Toast.makeText(AdressPicker.this, "An error has occured", Toast.LENGTH_LONG).show();
        }
    });

}

现在从这里调用传递标记的方法

public void applyGeoCode(Marker marker){
      double lat = marker.getPosition().latitude;
      double lng = marker.getPosition().longitude;
      marker.setSnippet(dropOffAddress);
      marker.showInfoWindow();
      editor.putString("dropOffAddress", dropOffAddress);
      editor.putString("lat", String.valueOf(lat));
      editor.putString("lng", String.valueOf(lng));
      editor.apply();
}

然后这样调用

        @Override
        public void onMarkerDragEnd(Marker marker) {
            reverseGeocode(String.valueOf(lat), String.valueOf(lng), marker);
        }