如何从 Retrofit2 获得字符串响应?
Posted
技术标签:
【中文标题】如何从 Retrofit2 获得字符串响应?【英文标题】:How to get string response from Retrofit2? 【发布时间】:2016-07-31 03:44:25 【问题描述】:我正在做 android,正在寻找一种方法来做一个超级基本的 http GET/POST 请求。我不断收到错误消息:
java.lang.IllegalArgumentException: Unable to create converter for class java.lang.String
网络服务:
public interface WebService
@GET("/projects")
Call<String> jquery();
然后在我的java中:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://jquery.org")
// .addConverterFactory(GsonConverterFactory.create())
.build();
WebService service = retrofit.create(WebService.class);
Call<String> signin = service.jquery();
Toast.makeText(this, signin.toString(), Toast.LENGTH_LONG).show();
我实际上只是尝试使用 GET 请求查询 jquery.org/projects 并返回它响应的字符串。怎么了?
如果我尝试实现自定义转换器(我在网上找到了一些示例),它会抱怨我没有实现抽象方法 convert(F),而这些示例都没有。
谢谢。
【问题讨论】:
【参考方案1】:将 Retrofit2 和 ScalarsConverterFactory 添加到您的 Retrofit.Builder。
adapterBuilder = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
要使用 ScalarsCoverter,请将以下依赖项添加到您的构建 graddle
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Adding Retrofit2
For API Call use:
Call <String> *****
安卓代码:
.enqueue(new Callback<String>()
@Override
public void onResponse(Call<String> call, Response<String> response)
Log.i("Response", response.body().toString());
//Toast.makeText()
if (response.isSuccessful())
if (response.body() != null)
Log.i("onSuccess", response.body().toString());
else
Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
【讨论】:
优秀的答案...添加单行 .addConverterFactory(ScalarsConverterFactory.create()) 解决了我的问题.... 很好,它适用于 response.body().toString()。但是如果 response.errorBody().toString() 不起作用,请帮助我 adapterBuilder = new Retrofit.Builder() .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create());这段代码对我有用。我有 2 个调用接口(第一个 JSON,第二个字符串) compile 已过时,已替换为 implementation。两个库的最新版本都是 2.9.0 依赖项应该如下: implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Adding Retrofit2 【参考方案2】:我查看了 Retrofit 库,发现它根据 Call<T>
中的类型类解析响应。所以你有两个选择:
第一种:根据服务器的响应创建一个类。
第二个:获取响应并自己处理(不推荐Retrofit已经处理它。那么为什么要使用Retrofit,因为它是为这项工作量身定制的)。无论如何,而不是Call<String>
使用Call<ResponseBody>
和Call<ResponseBody> signin = service.jquery();
在此之后放置以下
call.enqueue(new Callback<ResponseBody>()
@Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit)
// handle success
String result = response.body().string();
@Override
public void onFailure(Throwable t)
// handle failure
);
【讨论】:
什么是贡献者?它找不到它。 我编辑了它是 ResponseBody 其他变化是 body().string() 使用 ResponseBody 代替 String 有效。谢谢@ugur【参考方案3】:要以字符串形式获取响应,您必须编写一个转换器并在初始化Retrofit
时传递它。
这里是步骤。
初始化改造。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL_BASE)
.addConverterFactory(new ToStringConverterFactory())
.build();
return retrofit.create(serviceClass);
用于将Retrofit's ResponseBody
转换为String
的转换器类
public class ToStringConverterFactory extends Converter.Factory
private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit)
if (String.class.equals(type))
return new Converter<ResponseBody, String>()
@Override
public String convert(ResponseBody value) throws IOException
return value.string();
;
return null;
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit)
if (String.class.equals(type))
return new Converter<String, RequestBody>()
@Override
public RequestBody convert(String value) throws IOException
return RequestBody.create(MEDIA_TYPE, value);
;
return null;
并且在执行service.jquery();
之后,signin
将包含 JSON 响应。
【讨论】:
【参考方案4】:您可以尝试以下方法:
build.gradle 文件:
dependencies
...
compile 'com.squareup.retrofit2:retrofit:2.0.1'
...
WebAPIService:
@GET("/api/values")
Call<String> getValues();
活动文件:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL_BASE)
.build();
WebAPIService service = retrofit.create(WebAPIService.class);
Call<String> stringCall = service.getValues();
stringCall.enqueue(new Callback<String>()
@Override
public void onResponse(Call<String> call, Response<String> response)
Log.i(LOG_TAG, response.body());
@Override
public void onFailure(Call<String> call, Throwable t)
Log.e(LOG_TAG, t.getMessage());
);
我已经使用我的 Web 服务 (ASP.Net WebAPI) 进行了测试:
public class ValuesController : ApiController
public string Get()
return "value1";
Android Logcat 输出:04-11 15:17:05.316 23097-23097/com.example.multipartretrofit I/AsyncRetrofit2: value1
希望对你有帮助!
【讨论】:
【参考方案5】: call.enqueue(new Callback<Object>()
@Override
public void onResponse(@NonNull Call<Object> call, @NonNull Response<Object> response)
if (response.isSuccessful())
Gson gson = new Gson();
String successResponse = gson.toJson(response.body());
Log.d(LOG_TAG, "successResponse: " + successResponse);
else
try
if (null != response.errorBody())
String errorResponse = response.errorBody().string();
Log.d(LOG_TAG, "errorResponse: " + errorResponse);
catch (Exception e)
e.printStackTrace();
@Override
public void onFailure(@NonNull Call<Object> call, @NonNull Throwable t)
);
【讨论】:
【参考方案6】:只需在 intercepror 中使用日志级别BODY
:
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()....
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addNetworkInterceptor(httpLoggingInterceptor);
你可以在 logcat 中看到 body,如下所示:
D/OkHttp: "blablabla":1,....
D/OkHttp: <-- END HTTP (1756-byte body)
此解决方案仅用于调试,不适用于直接在代码中获取字符串。
【讨论】:
【参考方案7】:我更改了响应类型,而不是像这样添加 ScalarsConverterFactory
interface YourApiService
@GET("/endpoint")
fun getResponse(): Call<ResponseBody>
然后就可以通过
获取字符串对象了val str = response.body().toString()
【讨论】:
【参考方案8】:认为现在回答可能为时已晚,只需使用response.body()?.string()
,您的回复就会以字符串形式出现。
【讨论】:
【参考方案9】:String body = new String(((TypedByteArray) response.getBody()).getBytes());
如果你找到了
java.lang.ClassCastException: retrofit.client.UrlConnectionClient$TypedInputStream cannot be cast to retrofit.mime.TypedByteArray
然后把它放在你的 RestAdapter 中
.setLogLevel(RestAdapter.LogLevel.FULL)
例如:
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(Root_url)
.build();
【讨论】:
以上是关于如何从 Retrofit2 获得字符串响应?的主要内容,如果未能解决你的问题,请参考以下文章
使用 RxJava2 和 Retrofit2 时如何访问响应头?