【问题标题】:How can I debug my retrofit API call?如何调试我的改造 API 调用?
【发布时间】:2018-01-20 14:52:47
【问题描述】:

我正在使用改造从 Flickr api 获取一些数据。我正在调用的方法如下所示:

public static List<String> getImageIds(int size) {
    Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
    Log.d("TEMP_TAG", "photo url: " + call.request().url().toString());
    photoIds = new ArrayList<String>();

    call.enqueue(new Callback<PhotosList>(){
        @Override
        public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
            Log.d("TEMP_TAG", "it's getting here");
            PhotosList photosList = response.body();
            List<Photo> photos = photosList.getPhotos().getPhoto();

            for(Photo photo : photos) {
                Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
                photoIds.add(photo.getId());
            }
        }

        @Override
        public void onFailure(Call<PhotosList> call, Throwable t) {
            // TODO: Clean up
            Log.d("TEMP_TAG", "photoId: ");
        }
    });
    Log.d("TEMP_TAG", "it's getting here too");
    return photoIds;
}

但是它永远不会进入onResponse() 方法。 onResponse() 中的第一条日志语句从不打印,onFailure() 中的日志语句也不会打印。当我尝试在浏览器中输入call.request().url().toString() 返回的 URL 时,它工作正常,并且我得到了预期的 JSON。为什么我的 enqueue() 方法永远不会触发?

感谢您的帮助!

【问题讨论】:

  • 这不是一个真正的答案,但我个人的建议是在测试新的网络呼叫时始终使用 Charles 或 Postman 之类的东西。这样您就可以看到您发送的内容和收到的原始格式的内容。
  • 另外,删除日志Log.d("TEMP_TAG", "photo url: " + call.request().url().toString()); 并查看它是否有效(call.request() 元素可能在调用发生之前就已使用)

标签: android json rest retrofit retrofit2


【解决方案1】:

HttpLoggingInterceptor 与 Retrofit 一起使用。

如果这有帮助,请将其添加到您的 build.gradle 中 -

//Retrofit and OkHttp for Networking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//Logging Network Calls
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'

在你的 APIClient class 中添加这个 -

public class ApiClient {
    private static Retrofit retrofit = null;

    public static Retrofit getClient(){

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build();


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

Kotlin 代码

val interceptor : HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }

val client : OkHttpClient = OkHttpClient.Builder().apply {
            addInterceptor(interceptor)
        }.build()


fun getService(): Service {
        return Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(LiveDataCallAdapterFactory())
                .client(client)
                .build()
                .create(Service::class.java)
    }

您将能够记录您进行的改造网络调用。

如果您需要更多信息,请告诉我。

【讨论】:

  • 这只是记录。实际调试呢?一个有断点?出于某种原因,获取响应体的字段永远停留在“收集数据......”上。见这里:i.imgur.com/SCEL7K2.png。怎么会这样?我该怎么做才能让它有价值?
  • 根据截图,response.body() 已经显示errorCode 的值是0,此外,您可以使用评估表达式在调试模式下运行特定命令。您可以从here 了解更多关于 Evaluate Expression
【解决方案2】:

一个记录 HTTP 请求和响应数据的 OkHttp 拦截器。

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(logging)
    .build();

您可以随时调用setLevel更改日志级别。

有 4 个级别:NONE、BASIC、HEADERS、BODY

要登录到自定义位置,请将Logger 实例传递给构造函数。

HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new 
Logger() {
@Override public void log(String message) {
    Log.d(TAG, "message: ");
    }
});

来自 Gradle

compile 'com.squareup.okhttp3:logging-interceptor:(insert latest version)'

关注reference

已编辑:我还发现 this library 具有非常好的结构和干净的日志。试试看!!

【讨论】:

  • 嗯,这似乎对我没有任何帮助。使用上面的代码并将HttpLoggingInterceptor 放在进行调用的方法中,但没有任何输出。
  • 您是否使用此 Retrofit#client(client) 添加了用于改造的客户端?
  • 是的,我确实将.client(client) 添加到了我正在构建我的改造对象的链中
  • 因为OkHttp是按照Builder模式设计的,所以在调用.build()之前要小心的用HttpLoggingInterceptor实现OkHttp
  • 您可能需要添加如何初始化 Retrofit、Gson 和任何适配器的代码
【解决方案3】:

您可以使用以下类来记录 API 调用

import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor

object HTTPLogger {
    fun getLogger(): OkHttpClient {
        /*
         * OKHTTP interceptor to log all API calls
         */
        val interceptor = HttpLoggingInterceptor()
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        val client = OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build()
        return client
    }
}

然后你可以像这样在你的改造实例类中调用这个类

import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitClientInstance {
    private var retrofit: Retrofit? = null
    val retrofitInstance: Retrofit?
        get() {
            if (retrofit == null) {
                retrofit = Retrofit.Builder()
                        .baseUrl(Constants.BASE_URL)
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create())
                        .client(HTTPLogger.getLogger())
                        .build()
            }
            return retrofit
        }
}

需要的依赖是

implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'

【讨论】:

    猜你喜欢
    • 2018-05-26
    • 2021-05-24
    • 2019-11-21
    • 2021-08-05
    • 2021-10-28
    • 2020-11-11
    • 1970-01-01
    • 2016-04-17
    • 1970-01-01
    相关资源
    最近更新 更多