android - 将 Retrofit RestAdapter.LogLevel 设置为 FULL 以外的任何值都会导致 Empty Response Body

标签 android json rest gson retrofit

我的项目中有以下 3 个类和 1 个接口(interface)。将日志记录设置为 NONE 会导致“成功”,但响应主体为空(参见下面的 getMovies()->success())。该错误中输出的 URL 可以剪切并粘贴到浏览器中,并且可以完美运行。但是,如果我将日志记录更改为 FULL 一切正常,那么我的 API key 就会在 LogCat 输出中清晰可见。

public class RestClient {

    private ApiService apiService;

    public RestClient(String endpoint, boolean enableLogging) {

        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new ItemTypeAdapterFactory())
                .setDateFormat("yyyy-MM-dd")
                .setPrettyPrinting()
                .excludeFieldsWithoutExposeAnnotation()
                .create();

        RestAdapter restAdapter = new RestAdapter.Builder()
                .setLogLevel(BuildConfig.DEBUG && enableLogging ? RestAdapter.LogLevel.FULL : RestAdapter.LogLevel.NONE)
                .setEndpoint(endpoint)
                .setConverter(new GsonConverter(gson))
                .setRequestInterceptor(new SessionRequestInterceptor())
                .build();

        apiService = restAdapter.create(ApiService.class);
    }

    public ApiService getApiService() {
        return apiService;
    }

}


public class ServiceEventHandler {

    private boolean isRetrofitLoggingEnabled;
    private String rottenTomatoesUrl;
    private String rottenTomatoesApiKey;

    public ServiceEventHandler(Context context) {
        isRetrofitLoggingEnabled = Boolean.valueOf(context.getString(R.string.retrofit_logging_enabled));
        rottenTomatoesUrl = context.getString(R.string.movies_url);
        rottenTomatoesApiKey = context.getString(R.string.rotten_tomatoes_api_key); /* Look in res/values/secret.xml */
        if (rottenTomatoesApiKey.equals("REPLACE WITH YOUR KEY")) {
            Toast.makeText(context, context.getString(R.string.error_replace_api_key), Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 'IN THEATER' MOVIES
     */
    @Subscribe
    public void getMovies(final GetMoviesEvent event) {
        /**
         * rotten_tomatoes_api_key is stored in a strings resource file named secret.xml and
         * located in res/values, but secret.xml has been added to .gitignore so my key doesn't
         * end up in source control.
         *
         * simply create your own res/values/secret.xml file with your own Rotten Tomatoes API
         * key and the app will run as expected.
         */
        ApiService apiService = new RestClient(rottenTomatoesUrl, isRetrofitLoggingEnabled).getApiService();
        apiService.getMovies(rottenTomatoesApiKey, event.getPageNumber(), event.getPageLimit(), new RestCallback<Movies>(event.getCallNumber()) {
            @Override
            public void success(Movies movies, Response response) {
                if (response.getBody().length() > 0) {
                    EventBus.post(movies);
                } else {
                    EventBus.post(new APIErrorEvent(RetrofitError.unexpectedError(response.getUrl(), new HttpException("Empty Body")), event.getCallNumber()));
                }
            }
        });
    }
}


public abstract class RestCallback<T> implements Callback<T> {

    private int callNumber;

    public RestCallback(int callNumber) {
        this.callNumber = callNumber;
    }

    @Override
    public void failure(RetrofitError error) {
        EventBus.post(new APIErrorEvent(error, this.callNumber));
    }

    public int getCallNumber() {
        return callNumber;
    }
}


public interface ApiService {

    final static String APPSETTINGS = "/application_settings.json";
    final static String MOVIES = "/in_theaters.json";

    // IN THEATER MOVIES
    @GET(MOVIES)
    void getMovies(@Query("apikey") String key, @Query("page") int page, @Query("page_limit") int page_limit, Callback<Movies> cb);
}

最佳答案

response.getBody() 将返回一个 TypedInput,其长度方法 ( http://square.github.io/retrofit/javadoc/retrofit/mime/TypedInput.html#length-- ) 不保证在存在响应主体时返回大于零的数字。小于或等于 0 的值并不意味着你没有 body ,只是它不能告诉你它有多长。

猜测仅在日志记录关闭时才显示的原因是支持日志记录所需的缓冲详细信息。

您可能希望在 onSuccess 中围绕该长度以外的其他内容进行测试(例如:响应状态代码或在 Movies 对象上。

关于android - 将 Retrofit RestAdapter.LogLevel 设置为 FULL 以外的任何值都会导致 Empty Response Body,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28654932/

相关文章:

android - 错误 Android 模拟器在 Android Studio 中被杀死

java - 无法从 Eclipse 中删除链接源

android - API PHP 查询正确,但向 Android 客户端返回空

json - TreeMap<String, String> 到 json

javascript - 跟踪文件

安卓: GridView

PHP Slim Framework REST API - 在每个路由之前验证访问 token ?

php - 使用 Postman 通过原始 JSON 发送 POST 数据

php - 如何使用 mockbin API 正确创建一个 bin?

ruby-on-rails - 使用 curl 将 JSON 数据发布到简单的 Rails 应用程序