将 Retrofit RestAdapter.LogLevel 设置为 FULL 以外的任何值都会导致 Empty Response Body
Setting Retrofit RestAdapter.LogLevel to anything other than FULL results in Empty Response Body
我的项目中有以下 3 个 类 和 1 个接口。将日志记录设置为 NONE 会导致 "success",但响应主体为空(参见下面的 getMovies()->success())。该错误中输出的 URL 可以剪切并粘贴到浏览器中,并且可以完美运行。如果我将日志记录更改为 FULL 一切正常,但是,我的 API 密钥然后在 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()
将 return TypedInput 及其长度方法 (http://square.github.io/retrofit/javadoc/retrofit/mime/TypedInput.html#length--) 不保证 return 当响应 [=22] =] 存在。小于或等于 0 的值并不意味着您没有 body,只是它不能告诉您它有多长。
我猜测只有在关闭日志记录时才显示的原因是支持日志记录所需的缓冲详细信息。
您可能希望在 onSuccess
中围绕该长度以外的其他内容进行测试(例如:响应状态代码或 Movies
object.
我的项目中有以下 3 个 类 和 1 个接口。将日志记录设置为 NONE 会导致 "success",但响应主体为空(参见下面的 getMovies()->success())。该错误中输出的 URL 可以剪切并粘贴到浏览器中,并且可以完美运行。如果我将日志记录更改为 FULL 一切正常,但是,我的 API 密钥然后在 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()
将 return TypedInput 及其长度方法 (http://square.github.io/retrofit/javadoc/retrofit/mime/TypedInput.html#length--) 不保证 return 当响应 [=22] =] 存在。小于或等于 0 的值并不意味着您没有 body,只是它不能告诉您它有多长。
我猜测只有在关闭日志记录时才显示的原因是支持日志记录所需的缓冲详细信息。
您可能希望在 onSuccess
中围绕该长度以外的其他内容进行测试(例如:响应状态代码或 Movies
object.