使用 Retrofit 2 在 Java Android 中从方法返回字符串。

huangapple go评论70阅读模式
英文:

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 = &quot;39.748378&quot;, lng = &quot;-91.857558&quot;, placeId;

 Map&lt;String, String&gt; query = new HashMap&lt;&gt;();
    query.put(&quot;latlng&quot;, lat+&quot;,&quot;+lng);
    query.put(&quot;key&quot;,&quot;API_KEY&quot;);

public void getPlaceId(final Map&lt;String, String&gt; query) {
    String BASE_URL = &quot;https://maps.googleapis.com/maps/&quot;;
    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&lt;PlacesFoo&gt; call = service.loadPlace(query);
    call.enqueue(new Callback&lt;PlacesFoo&gt;() {
      @Override
      public void onResponse(Call&lt;PlacesFoo&gt; call, Response&lt;PlacesFoo&gt; response) {
        if(response.isSuccessful()) {
          Log.e(&quot;getPlaceId&quot;, &quot; Valid Response: &quot; + response.body());
          placeId = response.body().getResults().get(0).getPlaceId();
        } else {
          System.out.println(response.errorBody());
        }
      }

      @Override
      public void onFailure(Call&lt;PlacesFoo&gt; call, Throwable t) {
        t.printStackTrace();
        Log.e(&quot;getPlaceId&quot;, &quot; Error Response: &quot; + t);
      }
    });
    //return placeId;
  }

Interface for API

public interface PlacesInterface {
   
    // https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&amp;key=API_KEY
    @GET(&quot;api/geocode/json&quot;)
    Call&lt;PlacesFoo&gt; loadPlace(@QueryMap Map&lt;String, String&gt; options);

}

POJO for API reply

public class PlacesFoo {
@SerializedName(&quot;plus_code&quot;)
@Expose
private PlusCode plusCode;
@SerializedName(&quot;results&quot;)
@Expose
private List&lt;Result&gt; results = null;
@SerializedName(&quot;status&quot;)
@Expose
private String status;
public PlusCode getPlusCode() {
return plusCode;
}
public void setPlusCode(PlusCode plusCode) {
this.plusCode = plusCode;
}
public List&lt;Result&gt; getResults() {
return results;
}
public void setResults(List&lt;Result&gt; results) {
this.results = results;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public class AddressComponent {
@SerializedName(&quot;long_name&quot;)
@Expose
private String longName;
@SerializedName(&quot;short_name&quot;)
@Expose
private String shortName;
@SerializedName(&quot;types&quot;)
@Expose
private List&lt;String&gt; 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&lt;String&gt; getTypes() {
return types;
}
public void setTypes(List&lt;String&gt; types) {
this.types = types;
}
}
public class Bounds {
@SerializedName(&quot;northeast&quot;)
@Expose
private Northeast_ northeast;
@SerializedName(&quot;southwest&quot;)
@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(&quot;location&quot;)
@Expose
private Location location;
@SerializedName(&quot;location_type&quot;)
@Expose
private String locationType;
@SerializedName(&quot;viewport&quot;)
@Expose
private Viewport viewport;
@SerializedName(&quot;bounds&quot;)
@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(&quot;lat&quot;)
@Expose
private Double lat;
@SerializedName(&quot;lng&quot;)
@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(&quot;lat&quot;)
@Expose
private Double lat;
@SerializedName(&quot;lng&quot;)
@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(&quot;lat&quot;)
@Expose
private Double lat;
@SerializedName(&quot;lng&quot;)
@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(&quot;compound_code&quot;)
@Expose
private String compoundCode;
@SerializedName(&quot;global_code&quot;)
@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(&quot;compound_code&quot;)
@Expose
private String compoundCode;
@SerializedName(&quot;global_code&quot;)
@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(&quot;address_components&quot;)
@Expose
private List&lt;AddressComponent&gt; addressComponents = null;
@SerializedName(&quot;formatted_address&quot;)
@Expose
private String formattedAddress;
@SerializedName(&quot;geometry&quot;)
@Expose
private Geometry geometry;
@SerializedName(&quot;place_id&quot;)
@Expose
private String placeId;
@SerializedName(&quot;plus_code&quot;)
@Expose
private PlusCode_ plusCode;
@SerializedName(&quot;types&quot;)
@Expose
private List&lt;String&gt; types = null;
public List&lt;AddressComponent&gt; getAddressComponents() {
return addressComponents;
}
public void setAddressComponents(List&lt;AddressComponent&gt; 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&lt;String&gt; getTypes() {
return types;
}
public void setTypes(List&lt;String&gt; types) {
this.types = types;
}
}
public class Southwest {
@SerializedName(&quot;lat&quot;)
@Expose
private Double lat;
@SerializedName(&quot;lng&quot;)
@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(&quot;lat&quot;)
@Expose
private Double lat;
@SerializedName(&quot;lng&quot;)
@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(&quot;northeast&quot;)
@Expose
private Northeast northeast;
@SerializedName(&quot;southwest&quot;)
@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(&quot;PlaceID&quot;,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&lt;PlacesFoo&gt; call = service.loadPlace(query);
call.enqueue(new Callback&lt;PlacesFoo&gt;() {
@Override
public void onResponse(@NotNull Call&lt;PlacesFoo&gt; call, @NotNull Response&lt;PlacesFoo&gt; 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&lt;PlacesFoo&gt; 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&lt;String, String&gt; query, OnPlaceIdFoundListener callback) {
String BASE_URL = &quot;https://maps.googleapis.com/maps/&quot;;
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&lt;PlacesFoo&gt; call = service.loadPlace(query);
call.enqueue(new Callback&lt;PlacesFoo&gt;() {
@Override
public void onResponse(Call&lt;PlacesFoo&gt; call, Response&lt;PlacesFoo&gt; response) {
if(response.isSuccessful()) {
Log.e(&quot;getPlaceId&quot;, &quot; Valid Response: &quot; + response.body());
String placeId = response.body().getResults().get(0).getPlaceId();
callback.onPlaceIdFound(placeId); // @@here@@!!!!!
} else {
System.out.println(response.errorBody());
callback.onPlaceIdFound(&quot;&quot;); // @@here@@!!!!!
}
}
@Override
public void onFailure(Call&lt;PlacesFoo&gt; call, Throwable t) {
t.printStackTrace();
callback.onPlaceIdFound(&quot;&quot;); // @@here@@!!!!!
Log.e(&quot;getPlaceId&quot;, &quot; Error Response: &quot; + t);
}
});
//return placeId;
}

then use your method.

getPlaceId(query, new OnPlaceIdFoundListener() {
@Override
public void onPlaceIdFound(String placeId) {
Log.d(&quot;TAG&quot;, &quot;place id is found = &quot;+ placeId);
}
});

huangapple
  • 本文由 发表于 2020年8月17日 03:06:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/63440933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定