gpt4 book ai didi

java - 使用 JSON 的 Volley REST 客户端

转载 作者:太空狗 更新时间:2023-10-29 14:52:23 25 4
gpt4 key购买 nike

我想与仅以 JSON 响应的 RESTful 网络服务进行交互。来自服务器的任何成功响应都具有以下语法:

{
"code": int code,
"data": object or list of objects
}

错误响应时:

{
"code": int code,
"error": string,
"details": string
}

所以我在我的 Android 项目中创建了两个这样的类(用于 GSON 反射):

public class ErrorEntity {
private String details;
private String error;
private int code;

public ErrorEntity() {
// Stub constructor
}

public String getDetails() {
return details;
}

public String getError() {
return error;
}

public int getCode() {
return code;
}
}

为了获得成功的响应,我做了一个通用的,因为我不想在覆盖的 parseNetworkResponse 上解析 JSON 数据:

public class SuccessfulEntity<T> {

private T data;
private int code;

public SuccessfulEntity() {
// Stub content
}

public T getData() {
return data;
}

public int getCode() {
return code;
}
}

现在,因为我的 RESTful 服务器需要一些自定义 header ,所以我需要创建一个 Request 子类,但我不知道我需要从哪个类继承。
我看到了这个问题:Send POST request with JSON data using Volley并想做那样的事情。

基本上,我想创建一个新类 (VolleyRestClient),它具有 GET、POST、DELETE 方法和 API 路由,并通过此类发出我需要执行的所有请求。

该类的方法需要创建一个新的自定义请求并解析新的对象响应,如 SuccessfulEntity 和 ErrorEntity,然后在调用 VolleyRestClient 的服务/线程中解析数据。

我该怎么做?

最佳答案

经过与泛型和类型删除的长期斗争,我终于做到了。
因此,我将这篇文章发布给与我有同样问题并且需要解决方案而不用担心的人。

我的 ErrorEntity 和我的 SuccessfulEntity 仍然相同,但我创建了一个名为 RepositoryListener 的新接口(interface),如下所示:

public interface RepositoryListener {
public abstract void onErrorResponse(int code, String details);
public abstract void onSuccessfulResponse(int code, Object obj);
public abstract void onSuccessfulResponse2(int code, List<Object> obj);
}

然后我创建了一个类 VolleyRestClient,如下所示:

public class VolleyRestClient extends RestClient {

private final DefaultRetryPolicy mRetryPolicy;
private final RequestQueue mQueue;
private final Gson gson = new Gson();

public VolleyRestClient(Context context) {
// Default retry policy
mRetryPolicy = new DefaultRetryPolicy(2000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
mQueue = Volley.newRequestQueue(context);
}

public RequestQueue getQueue() {
// Method to push requests for image download
return mQueue;
}

@Override
public void GET(boolean obj, boolean needAuth, String url, Type type,
RepositoryListener listener) {
// Choose which listener to construct
Response.Listener<myResponse> mListener = obj ?
// This uses objects
makeSuccessfulListener(listener, type) :
// This uses list of objects
makeSuccessfulListener2(listener, type);

myRequest mRequest =
new myRequest(Request.Method.GET, needAuth, url,
mListener, makeErrorListener(listener));

mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}

@Override
public void POST(boolean needAuth, String url, String body, Type type, RepositoryListener listener) {
myRequest mRequest = new myRequest(Request.Method.POST, needAuth, url, body,
makeSuccessfulListener(listener, type), makeErrorListener(listener));

mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}

@Override
public void DELETE(boolean needAuth, String url, Type type, RepositoryListener listener) {
myRequest mRequest =
new myRequest(Request.Method.DELETE, needAuth, url,
makeSuccessfulListener(listener, type), makeErrorListener(listener));

mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}

private Response.Listener<myRequest> makeSuccessfulListener
(final RepositoryListener listener, final Type type) {
// TODO: test this method and implement lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
@Override
public void onResponse(myRequest response) {
SuccessfulEntity<Object> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse(response.getCode(), obj.getData());
}
};
}
}

private Response.Listener<myRequest> makeSuccessfulListener2
(final RepositoryListener listener, final Type type) {
// TODO: test lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
@Override
public void onResponse(myReqyest response) {
SuccessfulEntity<List<Object>> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse2(response.getCode(), obj.getData());
}
};
}
}

private Response.ErrorListener makeErrorListener(final RepositoryListener listener) {
return new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
try {
String jError = new String(error.networkResponse.data);
ErrorEntity mError = gson.fromJson(jError, ErrorEntity.class);
// Invoke listener closure
listener.onErrorResponse(error.networkResponse.statusCode, mError.getDetails());
} catch (Exception e) {
listener.onErrorResponse(404, e.getMessage());
}
}
};
}
}

这在很大程度上取决于我的需要,但我会解释一般概念。

所以我有一个自定义请求,正如我的问题中所解释的,我想将它解析为正确的数据类型。

更具体地说,我只能在 GET 请求(分页元素等...)上有一个 JSONArray 数据,所以我需要找到一种方法来区分这两种情况(当然,我知道在哪种情况下我将得到一个列表或一个对象)。

我们不能简单地在泛型类中使用它的类型从 Json 创建 POJO(因为 Java 类型删除),所以我们需要对象类型预先
但我们能做的是:

  • 在我们的自定义请求中,在 parseNetworkResponse 上执行类似的操作:

    @Override
    protected Response<myResponse> parseNetworkResponse(NetworkResponse response) {
    try {
    // Using server charset
    myResponse mResponse = new myResponse();

    mResponse.setCode(response.statusCode);
    mResponse.setBody(new String(response.data,
    HttpHeaderParser.parseCharset(response.headers)));

    // Return new response
    return Response.success(mResponse, HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
    // Normally use 'utf-8'
    return Response.error(new ParseError(e));
    }
    }

    换句话说,将原始字符串响应正文复制到新对象myResponse

  • 响应正文最终将在 VolleyRestClient 中解析,并将适当的类型作为 GET/DELETE/POST 参数传递;

  • makeSuccessfulListenermakeSuccessfulListener2 从 RepositoryListener 构造一个 Response.Listener,它有 3 个要覆盖的方法:onSuccessfulResponse 用于对象数据, onSuccessfulResponse2 用于对象数据列表,onErrorResponse 用于 4XX/5XX 错误;

    • 我们的数据对象/列表将被解析为更多泛型类型(List 和 Object),然后传递给我们的自定义监听器 RepositoryListener。

此方法的完整示例:

public void getNewLogin(String nickname, String password,
final TextView author, final TextView title, final TextView text) {

String json =
(new StringBuilder()
.append("{ \"nickname\": \"")
.append(nickname)
.append("\", \"password\": \"")
.append(password)
.append("\" }")).toString();

mRest.POST(false, "http://192.168.0.104:8000/api/session", json,
new TypeToken<SuccessfulEntity<Login>>(){}.getType(),
new RepositoryListener() {
@Override
public void onSuccessfulResponse2(int code, List<Object> obj) {
// Nothing happens here
}

@Override
public void onSuccessfulResponse(int code, Object obj) {
UserSession mInstance = UserSession.getInstance(null);
Login newLogin = (Login) obj;

title.setText(newLogin.getToken());
mInstance.setToken(newLogin.getToken());

Log.i("onSuccessfulResponse", mInstance.getToken());
Log.i("onSuccessfulResponse", mInstance.getmAuthorizationToken());

if (newLogin.getUser() != null) {
author.setText(newLogin.getUser().getNickname());
text.setText(newLogin.getUser().getUniversity());
}
}

@Override
public void onErrorResponse(int code, String error) {
Log.i("onErrorResponse", error);
}
});

mRest 是一个 VolleyRestClient 对象,它使用 Gson TypeToken 构造的类型向该地址执行 POST 请求(记住,我们的主体是一个 SuccessfulEntity)。

因为我们肯定会有一个对象数据,所以我们将覆盖 onSuccessfulResponse,将数据对象转换为 TypeToken 中使用的相同类型的 SuccessfulEntity,然后执行我们的脏活。

我不知道我是否清楚,这种方法有效,如果你们中的一些人需要澄清,请问:)

关于java - 使用 JSON 的 Volley REST 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34270897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com