- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想与仅以 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 参数传递;
makeSuccessfulListener 和 makeSuccessfulListener2 从 RepositoryListener 构造一个 Response.Listener,它有 3 个要覆盖的方法:onSuccessfulResponse 用于对象数据, onSuccessfulResponse2 用于对象数据列表,onErrorResponse 用于 4XX/5XX 错误;
此方法的完整示例:
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/
我目前正在测试 Volley 库。但是当请求失败 (404) 时,它不会再次执行,或者至少没有错误。但是缺少数据。如果请求失败,这是重试请求的正确方法吗? 提前致谢 req.setRetryPolic
我是新来从事Volley和缓存工作的:P。尽管我已经看过许多与Volley进行图像缓存有关的文章和帖子,但是我仍然不清楚采用Volley进行图像缓存的最佳/首选方式。像磁盘缓存还是内存? Volley
我想使用 Volley 从我的 Android 应用发送请求。 我已经把它包含在 build.gradle 中了 dependencies { ... compile 'com.andr
我的目标是从另一个类调用 Volley,这是一种非常简洁、模块化的方式,即: VolleyListener newListener = new VolleyListener()
我的代码是: class MyService extends Service{ public void onCreate(){ new ImageLoader(mReque
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我需要帮助来解决 Volley 库错误。我已使用 nodejs api 向服务器发送一些凭据以进行用户注册。在成功的情况下,当我的所有凭据对于创建新用户帐户都是唯一的时,它会向我显示所有响应等的所有内
我正在尝试完善我的应用程序中的错误处理,但我找不到 Volley 触发某些错误的集中位置以及原因。例如,我想知道如果我的请求的状态代码是 500 或更大,它肯定会触发 ServerError,但我似乎
当我在调试器中运行该方法时,数据按预期显示,但是每当我尝试使用它执行任何操作时,parentObject 的值都会返回为 null。 我只是想从服务器获取响应并将其存储为 JSONObject 以便在
我正在使用 Android Volley 缓存请求,这在我使用 GET 时工作正常,但由于某些原因我改用 POST。现在我想用不同的 POST 数据缓存相同的 URL。 请求 1 -> URL1,PO
我的情况是使用 Android-volley至 POST我的 json 对象,我可以成功发布所有内容,我的数据在服务器中可见,但服务器响应为 String不像 json ,这就是出现错误的原因。 co
我正在使用 volley 从 REST api 解析电影详细信息,并将解析的数据保存在名为 detailsMovies 的对象数组列表中。但是我无法在 onResponse 方法之外访问 ArrayL
我想知道如何解决这个问题。已完成代码的研究和替换,但问题仍然存在。 这是我使用 volley 的代码。 private void Regist(){ loading.setVisibility
如何创建一个单独的类,在其中定义所有关于 volley在另一个 Activity 中,我们直接传递 URL、CONTEXT 和 Get Response... 最佳答案 首先在Activity中创建回
我正在使用 volley 库并以 XML 格式获取响应。我想知道我们如何使用/volley 库解析响应。谢谢。 最佳答案 StringRequest req = new StringReque
当我在android studio中搜索 Volley 时,同时获取com.mcxiaoke.volley:library:1.0.19和com.mcxiaoke.volley:library-aar
我是 volley 和 android 的新手,我已经用 gradle 安装了 volley 并做了与官方教程相同的操作。但是没有响应,这意味着 Errorlistener 和 Responselis
当我在 Volley 中发出请求时,我收到 com.android.volley.ServerError 和响应代码 400。 我正在做这样的事情(通用示例代码): final String para
我引用了http://www.androidhive.info/2016/02/android-push-notifications-using-gcm-php-mysql-realtime-chat
当我将以下行添加到依赖项的 build.gradle 行时,Android Studio 显示此错误消息:compile 'com.android.volley:volley:1.0.0' apply
我是一名优秀的程序员,十分优秀!