【问题标题】:How to catch response on get method android retrofit?如何捕捉对 get 方法 android 改造的响应?
【发布时间】:2018-11-23 09:55:24
【问题描述】:

我是 android 开发的新手,正在努力学习它。我最近遇到了一个问题,当我使用 get 方法时,我得到如下响应:

由于后端给出的 status 为“0”,因此我无法捕获“response_data”数组。 谁能指导我如何才能得到回应。 谢谢。

API 客户端:

 public class ApiClient {
    private final static String BASE_URL = "http://api.xxxxxx.com/app/";
    public static ApiClient apiClient;
    private Retrofit retrofit = null;

    public static ApiClient getInstance() {
        if (apiClient == null) {
            apiClient = new ApiClient();
        }
        return apiClient;
    }
 public Retrofit getClient() {
        return getClient(null);
    }



    private Retrofit getClient(final Context context) {

        HttpLoggingInterceptor interceptor = new 
HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.readTimeout(60, TimeUnit.SECONDS);
        client.writeTimeout(60, TimeUnit.SECONDS);
        client.connectTimeout(60, TimeUnit.SECONDS);
        client.addInterceptor(interceptor);
        client.addInterceptor(new Interceptor() {
            @Override
            public okhttp3.Response intercept(Chain chain) throws 
IOException {
                Request request = chain.request();

                return chain.proceed(request);
            }
        });

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client.build())
                .addConverterFactory(GsonConverterFactory.create())
                .build();


        return retrofit;
    }

    }

主要活动:

public class MainActivity extends AppCompatActivity {

TextView tvResponse;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    tvResponse=findViewById(R.id.tvResponse);

    ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
    Call<ResponseData> responseDataCall=apiInterface.getData();
    responseDataCall.enqueue(new Callback<ResponseData>() {
        @Override
        public void onResponse(Call<ResponseData> call, Response<ResponseData> response) {
            if (response.isSuccessful() && response.body()!=null && response!=null){
                List<ResponseDataItem> data=response.body().getResponseData();

            }
        }

        @Override
        public void onFailure(Call<ResponseData> call, Throwable t) {
            t.printStackTrace();
        }
    });
}

}

响应数据:

public class ResponseData {
@SerializedName("response_data")
private List<ResponseDataItem> responseData;

@SerializedName("status")
private int status;

public void setResponseData(List<ResponseDataItem> responseData){
    this.responseData = responseData;
}

public List<ResponseDataItem> getResponseData(){
    return responseData;
}

public void setStatus(int status){
    this.status = status;
}

public int getStatus(){
    return status;
}

}

【问题讨论】:

  • 你能告诉我你的代码吗?
  • 这是一个简单的 JSON 解析。
  • @HudiIlfeld 好的,我正在提供我的代码。

标签: android get retrofit


【解决方案1】:

在这种情况下,你需要让 Gson 知道你想如何解析你的 json。 您可以为每个特定的类案例添加许多特定的TypeAdapter,或者您可以创建一个TypeAdapterFactory,用于解析您的所有json。请记住将其添加到您的 Retrofit 构建器中。

此代码示例是一个 TypeAdapterFactory,它将忽略 status 并仅将 response_data 解析为您的对象。

class ResponseDataTypeAdapterFactory implements TypeAdapterFactory {

    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
        TypeAdapter<JsonElement> elementTypeAdapter = gson.getAdapter(JsonElement.class);

        return new TypeAdapter<T>() {
            public void write(JsonWriter out, T value) throws IOException {
                delegate.write(out, value);
            }

            public T read(JsonReader reader) throws IOException {

                JsonElement jsonElement = elementTypeAdapter.read(reader);

                if (jsonElement.isJsonObject()) {
                    JsonObject jsonObject = jsonElement.getAsJsonObject();
                    if (jsonObject.has("response_data")) {
                       jsonElement = jsonObject.get("response_data");
                    }
                }

                return delegate.fromJsonTree(jsonElement);
            }
        };
    }
}

并且在您的改造构建器上

Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(ResponseDataTypeAdapterFactory())
    .create();

new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(client.build())
    .addConverterFactory(new GsonConverterFactory.create(gson))
    .build();

并且在Retrofit接口处,只需要调用response_datamapping对应的类即可。

public interface ApiInterface {

    @GET("/product-data")
    Call<List<ResponseDataItem>> fetchData();
}

通过此实现,您可以删除您的 ResponseData 类并只关心重要的模型。

【讨论】:

  • 好的,谢谢您的回复。先生,请告诉我捕获 json 数组的循环代码是什么。
  • 我已经编辑了答案->在Retrofit界面,只需要调用response_data映射对应的类即可。
  • 我只为这个答案编写了这个例子,如果你必须改变一些东西来编译,请在这里编辑。
【解决方案2】:

制作界面

public interface ApiInterface {

    @GET
    Call<JsonElement> getTimeDifference(@Url String url);
}

创建一个 Retrofit 客户端类

public class RetrofitClient {

    private static final String TAG = "RetrofitClient";

    public static Retrofit geBaseUrl() {
        Retrofit retrofit = null;
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        if (BuildConfig.DEBUG) {
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        }else{
            interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
        }         OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl("...your base url...")
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }


}

            String endpoint = "...your end point...";

            ApiInterface ret = RetrofitClient.geBaseUrl(url).create(ApiInterface.class);
            Call<JsonElement> call = ret.getTimeDifference(endpoint);
            call.enqueue(new Callback<JsonElement>() {
                @Override
                public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                    try {
                        Log.d("String", "onResponse:  response" + response.body().toString());

                    } catch (Exception e) {
                       
                    }
                }

                @Override
                public void onFailure(Call<JsonElement> call, Throwable t) {
                    Log.d("response", "onFailure: " + t + "      " + call);
                    
                }
            });

【讨论】:

    【解决方案3】:

    对于捕获响应,您可以使用 interceptor,例如 HttpLoggingInterceptor ,stetho,chuck

    创建改造实例

    //将拦截器添加到OkHttpClient

      OkHttpClient client=new OkHttpClient().newBuilder()
            .addNetworkInterceptor(new StethoInterceptor()) \\ StethoInterceptor
            .addInterceptor(new ChuckInterceptor(context))  \\  ChuckInterceptor
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.MINUTES)
            .writeTimeout(5, TimeUnit.MINUTES)
            .build();
    
    public static final String BASE_URL = "http://api.myservice.com/";
    Retrofit retrofit = new Retrofit.Builder()
      .baseUrl(BASE_URL)
      .addConverterFactory(GsonConverterFactory.create())
      .client(client)
      .build();
    

    用于听诊器拦截器

     implementation 'com.facebook.stetho:stetho:1.5.0'
     implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'
    

    夹头

     debugImplementation 'com.readystatesoftware.chuck:library:1.1.0'
     releaseImplementation 'com.readystatesoftware.chuck:library-no-op:1.1.0'
    

    【讨论】:

    • 上述的事情我都做了,但是JSON在哪里??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 2019-07-13
    • 2014-03-19
    • 2020-06-02
    相关资源
    最近更新 更多