英文:
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);
}
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论