英文:
Return string from method using Retrofit 2 for java Android
问题
以下是您提供的代码的翻译部分:
我正在尝试查询 Google 地图 API,根据纬度/经度获取位置的 placeId。我遇到的问题是,我的代码在 API 响应之前就移动到了返回语句,因此返回的字符串为空,而不是来自 API 的 placeId。有人能帮我找出我漏掉了什么吗?
<BR>**已编辑**<br>
我已将 getPlaceId 方法更改为返回 null,并将来自响应的 getPlaceId 分配给公共变量。我从 API 获取了数据,但似乎 JSON 没有被解析,因此变量仍为 null。
使用 Retrofit 的 getPlaceId 方法 <BR>
**已编辑**
String lat = "39.748378", lng = "-91.857558", placeId;
Map<String, String> query = new HashMap<>();
query.put("latlng", lat + "," + lng);
query.put("key", "API_KEY");
public void getPlaceId(final Map<String, String> query) {
String BASE_URL = "https://maps.googleapis.com/maps/";
Retrofit retrofit;
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(logging)
        .build();
retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build();
PlacesInterface service = retrofit.create(PlacesInterface.class);
Call<PlacesFoo> call = service.loadPlace(query);
call.enqueue(new Callback<PlacesFoo>() {
    @Override
    public void onResponse(Call<PlacesFoo> call, Response<PlacesFoo> response) {
        if (response.isSuccessful()) {
            Log.e("getPlaceId", " 有效的响应:" + response.body());
            placeId = response.body().getResults().get(0).getPlaceId();
        } else {
            System.out.println(response.errorBody());
        }
    }
    @Override
    public void onFailure(Call<PlacesFoo> call, Throwable t) {
        t.printStackTrace();
        Log.e("getPlaceId", " 错误的响应:" + t);
    }
});
//return placeId;
}
API 的接口
public interface PlacesInterface {
   
    // https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=API_KEY
    @GET("api/geocode/json")
    Call<PlacesFoo> loadPlace(@QueryMap Map<String, String> options);
}
用于 API 响应的 POJO
public class PlacesFoo {
    @SerializedName("plus_code")
    @Expose
    private PlusCode plusCode;
    @SerializedName("results")
    @Expose
    private List<Result> results = null;
    @SerializedName("status")
    @Expose
    private String status;
    // 其他代码部分...
}
请注意,这只是您提供的代码的翻译部分。如果您有进一步的问题或需要更多帮助,请随时提问。
英文:
I'm attempting to query google maps api to get the placeId of a location based on lat/lng.  The issue I'm having is the my code moves to the return statement before the API responds and as a result the return string is null instead of the placeId from the api.  Can someone help me figure out what I'm missing?
<BR>EDITED<br>
I have changed the getPlaceId method to return null and simply assign the getPlaceId from the response to a public variable.  I get the data from the API but it looks as if the json isn't being parsed, as a result the variable is still null.
getPlaceId method using retrofit<BR>
EDITED
String lat = "39.748378", lng = "-91.857558", placeId;
 Map<String, String> query = new HashMap<>();
    query.put("latlng", lat+","+lng);
    query.put("key","API_KEY");
public void getPlaceId(final Map<String, String> query) {
    String BASE_URL = "https://maps.googleapis.com/maps/";
    Retrofit retrofit;
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(logging)
            .build();
    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();
    PlacesInterface service = retrofit.create(PlacesInterface.class);
    Call<PlacesFoo> call = service.loadPlace(query);
    call.enqueue(new Callback<PlacesFoo>() {
      @Override
      public void onResponse(Call<PlacesFoo> call, Response<PlacesFoo> response) {
        if(response.isSuccessful()) {
          Log.e("getPlaceId", " Valid Response: " + response.body());
          placeId = response.body().getResults().get(0).getPlaceId();
        } else {
          System.out.println(response.errorBody());
        }
      }
      @Override
      public void onFailure(Call<PlacesFoo> call, Throwable t) {
        t.printStackTrace();
        Log.e("getPlaceId", " Error Response: " + t);
      }
    });
    //return placeId;
  }
Interface for API
public interface PlacesInterface {
   
    // https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=API_KEY
    @GET("api/geocode/json")
    Call<PlacesFoo> loadPlace(@QueryMap Map<String, String> options);
}
POJO for API reply
public class PlacesFoo {
@SerializedName("plus_code")
@Expose
private PlusCode plusCode;
@SerializedName("results")
@Expose
private List<Result> results = null;
@SerializedName("status")
@Expose
private String status;
public PlusCode getPlusCode() {
return plusCode;
}
public void setPlusCode(PlusCode plusCode) {
this.plusCode = plusCode;
}
public List<Result> getResults() {
return results;
}
public void setResults(List<Result> results) {
this.results = results;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public class AddressComponent {
@SerializedName("long_name")
@Expose
private String longName;
@SerializedName("short_name")
@Expose
private String shortName;
@SerializedName("types")
@Expose
private List<String> types = null;
public String getLongName() {
return longName;
}
public void setLongName(String longName) {
this.longName = longName;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public List<String> getTypes() {
return types;
}
public void setTypes(List<String> types) {
this.types = types;
}
}
public class Bounds {
@SerializedName("northeast")
@Expose
private Northeast_ northeast;
@SerializedName("southwest")
@Expose
private Southwest_ southwest;
public Northeast_ getNortheast() {
return northeast;
}
public void setNortheast(Northeast_ northeast) {
this.northeast = northeast;
}
public Southwest_ getSouthwest() {
return southwest;
}
public void setSouthwest(Southwest_ southwest) {
this.southwest = southwest;
}
}
public class Geometry {
@SerializedName("location")
@Expose
private Location location;
@SerializedName("location_type")
@Expose
private String locationType;
@SerializedName("viewport")
@Expose
private Viewport viewport;
@SerializedName("bounds")
@Expose
private Bounds bounds;
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
public String getLocationType() {
return locationType;
}
public void setLocationType(String locationType) {
this.locationType = locationType;
}
public Viewport getViewport() {
return viewport;
}
public void setViewport(Viewport viewport) {
this.viewport = viewport;
}
public Bounds getBounds() {
return bounds;
}
public void setBounds(Bounds bounds) {
this.bounds = bounds;
}
}
public class Location {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lng")
@Expose
private Double lng;
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}
public class Northeast {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lng")
@Expose
private Double lng;
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}
public class Northeast_ {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lng")
@Expose
private Double lng;
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}
public class PlusCode {
@SerializedName("compound_code")
@Expose
private String compoundCode;
@SerializedName("global_code")
@Expose
private String globalCode;
public String getCompoundCode() {
return compoundCode;
}
public void setCompoundCode(String compoundCode) {
this.compoundCode = compoundCode;
}
public String getGlobalCode() {
return globalCode;
}
public void setGlobalCode(String globalCode) {
this.globalCode = globalCode;
}
}
public class PlusCode_ {
@SerializedName("compound_code")
@Expose
private String compoundCode;
@SerializedName("global_code")
@Expose
private String globalCode;
public String getCompoundCode() {
return compoundCode;
}
public void setCompoundCode(String compoundCode) {
this.compoundCode = compoundCode;
}
public String getGlobalCode() {
return globalCode;
}
public void setGlobalCode(String globalCode) {
this.globalCode = globalCode;
}
}
public class Result {
@SerializedName("address_components")
@Expose
private List<AddressComponent> addressComponents = null;
@SerializedName("formatted_address")
@Expose
private String formattedAddress;
@SerializedName("geometry")
@Expose
private Geometry geometry;
@SerializedName("place_id")
@Expose
private String placeId;
@SerializedName("plus_code")
@Expose
private PlusCode_ plusCode;
@SerializedName("types")
@Expose
private List<String> types = null;
public List<AddressComponent> getAddressComponents() {
return addressComponents;
}
public void setAddressComponents(List<AddressComponent> addressComponents) {
this.addressComponents = addressComponents;
}
public String getFormattedAddress() {
return formattedAddress;
}
public void setFormattedAddress(String formattedAddress) {
this.formattedAddress = formattedAddress;
}
public Geometry getGeometry() {
return geometry;
}
public void setGeometry(Geometry geometry) {
this.geometry = geometry;
}
public String getPlaceId() {
return placeId;
}
public void setPlaceId(String placeId) {
this.placeId = placeId;
}
public PlusCode_ getPlusCode() {
return plusCode;
}
public void setPlusCode(PlusCode_ plusCode) {
this.plusCode = plusCode;
}
public List<String> getTypes() {
return types;
}
public void setTypes(List<String> types) {
this.types = types;
}
}
public class Southwest {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lng")
@Expose
private Double lng;
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}
public class Southwest_ {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lng")
@Expose
private Double lng;
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}
public class Viewport {
@SerializedName("northeast")
@Expose
private Northeast northeast;
@SerializedName("southwest")
@Expose
private Southwest southwest;
public Northeast getNortheast() {
return northeast;
}
public void setNortheast(Northeast northeast) {
this.northeast = northeast;
}
public Southwest getSouthwest() {
return southwest;
}
public void setSouthwest(Southwest southwest) {
this.southwest = southwest;
}
}
}
答案1
得分: 2
Retrofit 支持同步和异步请求执行。用户通过为服务方法设置返回类型(同步)或不设置返回类型(异步)来定义具体的执行方式。
编辑
你需要通过接口传递来自异步调用的结果
public interface MyCallback {
    void onSuccess(String placeId);
    void onError(String error);
}
然后你的调用将会是这样的:
getPlaceId(new MyCallback() {
    @Override
    public void onSuccess(String placeId) {
        // 在这里你会得到地点的 ID,你可以根据 ID 进行操作
        Log.e("PlaceID", placeId);
    }
    @Override
    public void onError(String error) {
        // 在发生错误的情况下
    }
});
Retrofit 调用
private void getPlaceId(MyCallback myCallback) {
    // ...
    // ...
    PlacesInterface service = retrofit.create(PlacesInterface.class);
    Call<PlacesFoo> call = service.loadPlace(query);
    call.enqueue(new Callback<PlacesFoo>() {
        @Override
        public void onResponse(@NotNull Call<PlacesFoo> call, @NotNull Response<PlacesFoo> response) {
            if (response.isSuccessful()) {
                String placeId = response.body().getResults().get(0).getPlaceId();
                myCallback.onSuccess(placeId);
            } else {
                if (response.errorBody() != null) {
                    myCallback.onError(response.errorBody().toString());
                }
            }
        }
        @Override
        public void onFailure(@NotNull Call<PlacesFoo> call, @NotNull Throwable t) {
            t.printStackTrace();
            myCallback.onError(t.getLocalizedMessage());
        }
    });
}
要了解异步和同步请求之间的区别,请查看此链接。
英文:
>Retrofit supports synchronous and asynchronous request execution. Users define the concrete execution by setting a return type (synchronous) or not (asynchronous) to service methods.
Edit
You need to pass the result from the Asynchronous call through interface
 public interface MyCallback {
void onSuccess(String placeId);
void onError(String error);
}
and your call will be like
getPlaceId(new MyCallback() {
@Override
public void onSuccess(String placeId) {
// here you get place Id you can do your work with id
Log.e("PlaceID",placeId);
}
@Override
public void onError(String error) {
// in case of error occurred
}
});
Retrofit call
  private void getPlaceId(MyCallback myCallback) {
.....
.....
PlacesInterface service = retrofit.create(PlacesInterface .class);
Call<PlacesFoo> call = service.loadPlace(query);
call.enqueue(new Callback<PlacesFoo>() {
@Override
public void onResponse(@NotNull Call<PlacesFoo> call, @NotNull Response<PlacesFoo> response) {
if (response.isSuccessful()) {
String placeId = response.body().getResults().get(0).getPlaceId();
myCallback.onSuccess(placeId);
} else {
if (response.errorBody() != null) {
myCallback.onError(response.errorBody().toString());
}
}
}
@Override
public void onFailure(@NotNull Call<PlacesFoo> call, @NotNull Throwable t) {
t.printStackTrace();
myCallback.onError(t.getLocalizedMessage());
}
});
}
to know the difference between Asynchronous and Synchronous request check this
答案2
得分: 0
首先创建一个如下的接口:
public interface OnPlaceIdFoundListener {
    void onPlaceIdFound(String placeId);
}
其次,你需要修改getPlaceId方法的签名和代码块,如下所示(看见"@@here@@!!!!!"标记处):
public void getPlaceId(final Map<String, String> query, OnPlaceIdFoundListener callback) {
    String BASE_URL = "https://maps.googleapis.com/maps/";
    Retrofit retrofit;
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(logging)
            .build();
    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();
    PlacesInterface service = retrofit.create(PlacesInterface.class);
    Call<PlacesFoo> call = service.loadPlace(query);
    call.enqueue(new Callback<PlacesFoo>() {
        @Override
        public void onResponse(Call<PlacesFoo> call, Response<PlacesFoo> response) {
            if(response.isSuccessful()) {
                Log.e("getPlaceId", " Valid Response: " + response.body());
                String placeId = response.body().getResults().get(0).getPlaceId();
                callback.onPlaceIdFound(placeId); // @@here@@!!!!!
            } else {
                System.out.println(response.errorBody());
                callback.onPlaceIdFound(""); // @@here@@!!!!!
            }
        }
        @Override
        public void onFailure(Call<PlacesFoo> call, Throwable t) {
            t.printStackTrace();
            callback.onPlaceIdFound(""); // @@here@@!!!!!
            Log.e("getPlaceId", " Error Response: " + t);
        }
    });
    //return placeId;
}
然后使用你的方法:
getPlaceId(query, new OnPlaceIdFoundListener() {
    @Override
    public void onPlaceIdFound(String placeId) {
         Log.d("TAG", "place id is found = " + placeId);
    }
});
英文:
first create an interface like below:
public interface OnPlaceIdFoundListener {
void onPlaceIdFound(String placeId);
}
second you should change signature and body of getPlaceId method like below (see "@@here@@!!!!!" sign):
public void getPlaceId(final Map<String, String> query, OnPlaceIdFoundListener callback) {
String BASE_URL = "https://maps.googleapis.com/maps/";
Retrofit retrofit;
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
PlacesInterface service = retrofit.create(PlacesInterface.class);
Call<PlacesFoo> call = service.loadPlace(query);
call.enqueue(new Callback<PlacesFoo>() {
@Override
public void onResponse(Call<PlacesFoo> call, Response<PlacesFoo> response) {
if(response.isSuccessful()) {
Log.e("getPlaceId", " Valid Response: " + response.body());
String placeId = response.body().getResults().get(0).getPlaceId();
callback.onPlaceIdFound(placeId); // @@here@@!!!!!
} else {
System.out.println(response.errorBody());
callback.onPlaceIdFound(""); // @@here@@!!!!!
}
}
@Override
public void onFailure(Call<PlacesFoo> call, Throwable t) {
t.printStackTrace();
callback.onPlaceIdFound(""); // @@here@@!!!!!
Log.e("getPlaceId", " Error Response: " + t);
}
});
//return placeId;
}
then use your method.
getPlaceId(query, new OnPlaceIdFoundListener() {
@Override
public void onPlaceIdFound(String placeId) {
Log.d("TAG", "place id is found = "+ placeId);
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论