【发布时间】:2019-08-23 08:27:32
【问题描述】:
Retrofit 2.0 的一个非常令人失望的特性是它不能准确地告诉它在解析响应时失败的地方。因此,在邮递员中,当我使用相同的正文发送请求时,我会收到如下登录响应:
{
"result": "success",
"response_code": 200,
"data": {
"id": "1",
"display_name": "admin",
"email": "payal@teckmovers.com",
"username": "admin",
"access_token": "8daa8e02ca432e51ae90912fbf63eeea"
}
}
但是当我在 Retrofit 中使用完全相同的主体发出完全相同的请求时,我得到了一个非常奇特的响应:{protocol=http/1.1, code=200, message=OK, url=http://192.168.0.52/evidya/wp-api/v1/user/login}。现在我已经解决了上述问题的其他相关问题,但没有一个对我有用。请帮忙。我的代码:
改造API接口:
public interface eVidyaApi {
@FormUrlEncoded
@POST("user/login")
Call<LoginResponse> loginUser(
@HeaderMap Map<String, String> headers,
@Field("email") String email,
@Field("password") String password
);
}
登录功能:
public void login() {
Log.d(TAG, "Login");
if (!validate()) {
onLoginFailed();
return;
}
final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this, R.style.MyDialogTheme);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
String email = _emailText.getText().toString();
String password = _passwordText.getText().toString();
Log.d(TAG, "login: "+email+" "+password);
// TODO: Implement your own authentication logic here.
Call<LoginResponse> loginResponseCall = evidya.loginUser(Common.getHeaders(), email, password);
loginResponseCall.enqueue(new Callback<LoginResponse>() {
@Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
progressDialog.dismiss();
if(!response.isSuccessful()){
Toast.makeText(LoginActivity.this, ""+response.message(), Toast.LENGTH_SHORT).show();
Log.d(TAG, "onResponse: fail "+response.code());
return;
}
Log.d(TAG, "onResponse: success"+response.code()+" "+response);
if(response.body()!=null){
String content="";
// _loginButton.setEnabled(false);
LoginResponse loginResponse = response.body();
content += "code:"+ response.code();
content += "token:"+ loginResponse.getData().getAccessToken();
content += "result"+ loginResponse.getResult();
content += "result"+ loginResponse.getData().getDisplayName();
// onLoginSuccess();
Log.d(TAG, "onResponse: login res"+content);
} else {
Toast.makeText(LoginActivity.this, "Invalid response from server", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(LoginActivity.this, "Cannot fetch request", Toast.LENGTH_SHORT).show();
}
});
}
LoginResponse.java
package com.example.evidya.Retrofit.Model.LoginModel;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class LoginResponse {
@SerializedName("result")
@Expose
private String result;
@SerializedName("response_code")
@Expose
private Integer responseCode;
@SerializedName("data")
@Expose
private Data data;
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public Integer getResponseCode() {
return responseCode;
}
public void setResponseCode(Integer responseCode) {
this.responseCode = responseCode;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
数据.java
package com.example.evidya.Retrofit.Model.LoginModel;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Data {
@SerializedName("id")
@Expose
private String id;
@SerializedName("display_name")
@Expose
private String displayName;
@SerializedName("email")
@Expose
private String email;
@SerializedName("username")
@Expose
private String username;
@SerializedName("access_token")
@Expose
private String accessToken;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
我的日志记录(ok hhttp),当单击登录按钮时显示错误的详细信息:
我的日志记录(ok hhttp),单击带有正确详细信息的登录按钮时:
基本上问题是我使用Log.d(TAG, "onResponse: success"+response.code()+" "+response); 来检查 onresponse 回调中的响应。而我应该做的就是不要卡在那里并检查 loginResponse 对象的值(来自LoginResponse loginResponse = response.body();)。因为 response.body 实际上是以对象形式存储响应。这就是改造中的工作方式。
【问题讨论】:
-
添加HttpLoggingInterceptor 以验证文本响应。还要检查日志中是否存在由于类型而导致的任何解析错误。
-
根据基本网址,您似乎正在尝试从本地网络调用 API。请确认设备是否在本地网络上。
-
我正在从我的模拟器中调用 api,并获得状态码为 200,同时登录时我也没有问题
-
是什么让你说这与解析有关?您是否确实验证了您收到了响应,但未能解析它?您能否像建议的那样添加日志拦截器并检查它。另外,请注意,不是由 Retrofit 来解析响应。改造与此分离。人们经常将它与 gson 一起使用,并假设它是一对一的关系,但事实并非如此。例如,您可以将它与 Moshi 一起使用,它具有出色的错误输出。
-
@Fred 我已经添加了我得到的 okhttp 日志记录,请检查它,如果你能发现一些错误。我刚才发现的一件事是响应代码是 200,这意味着成功响应,即使我在标题中输入了错误的信息,它应该生成“身份验证错误”消息。
标签: java android retrofit retrofit2