如何为跨类 Volley 方法调用创建适当的 Volley 侦听器
Posted
技术标签:
【中文标题】如何为跨类 Volley 方法调用创建适当的 Volley 侦听器【英文标题】:How to create a proper Volley Listener for cross class Volley method calling 【发布时间】:2016-02-05 17:58:46 【问题描述】:我的目标是从另一个班级调用 Volley,这是一种非常简洁、模块化的方式,即:
VolleyListener newListener = new VolleyListener();
VolleySingleton.getsInstance().somePostRequestReturningString(getApplicationContext(), newListener);
JSONObject data = newListener.getResponse();
但是让监听器部分工作以便能够从诸如
之类的方法访问结果数据时遇到了很多麻烦newListener.getResponse();
本网站上的一些问题大致概述了如何从其他班级设置凌空呼叫,例如:android Volley - How to isolate requests in another class。我已经成功地让方法调用工作了,但是现在将这些数据放入当前类以供使用已经造成了麻烦。
我的VolleySingleton
类中的操作为:
public void somePostRequestReturningString(final Context context,final VolleyListener<String> listener)
final String URL = "http://httpbin.org/ip";
JsonObjectRequest set = new JsonObjectRequest(Request.Method.GET, URL, ((String) null),
new Response.Listener<JSONObject>()
@Override
public void onResponse(JSONObject response)
listener.outPut = response.toString();
//Toast.makeText(context, response.toString(), Toast.LENGTH_LONG).show();
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
Log.d("Error.Response", error.toString());
);
mRequestQueue.add(set);
在监听器类中:
public class VolleyListener
public static String outPut;
private static Response.Listener<String> createSuccessListener()
return new Response.Listener<String>()
@Override
public void onResponse(String response)
outPut = response;
;
如何配置它以使其工作并允许 Volley 调用和从另一个类检索数据,特别是如何正确构建回调?
【问题讨论】:
【参考方案1】:对于您的要求,我建议您参考我的以下解决方案,希望它清楚且有帮助:
首先是界面:
public interface VolleyResponseListener
void onError(String message);
void onResponse(Object response);
然后在你的助手类中(我将它命名为VolleyUtils
类):
public static void makeJsonObjectRequest(Context context, String url, final VolleyResponseListener listener)
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(url, null, new Response.Listener<JSONObject>()
@Override
public void onResponse(JSONObject response)
listener.onResponse(response);
, new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
listener.onError(error.toString());
)
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response)
try
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
catch (UnsupportedEncodingException e)
return Response.error(new ParseError(e));
catch (JSONException je)
return Response.error(new ParseError(je));
;
// Access the RequestQueue through singleton class.
VolleySingleton.getInstance(context).addToRequestQueue(jsonObjectRequest);
然后,在你的 Activity 类中,你可以像下面这样调用:
VolleyUtils.makeJsonObjectRequest(mContext, url, new VolleyResponseListener()
@Override
public void onError(String message)
@Override
public void onResponse(Object response)
);
您可以参考以下问题了解更多信息(正如我昨天告诉您的):
Android: How to return async JSONObject from method using Volley?
POST Request Json file passing String and wait for the response Volley
Android/Java: how to delay return in a method
【讨论】:
我不喜欢基本 Volley 语法,几乎与您在示例中的 Activity 类中放置的内容相同。我希望摆脱它的冗长本质并简化。如果那是不可能的/太多的努力是真正值得的,我可能只是继续前进。你怎么看? 在我的第三个链接中,你会找到“Utils.makeJsonObjectRequest_Callable”,不知道是不是你喜欢的。如果没有,我认为没有比你更漂亮的语法了。或者你可以在这里阅读***.com/questions/16904741/…【参考方案2】:Volley 擅长用于填充 UI 的 RPC 类型的操作,例如 获取一页搜索结果作为结构化数据。它集成了 轻松使用任何协议,开箱即用,支持原始 字符串、图像和 JSON。通过提供内置支持 您需要的功能,Volley 将您从编写样板代码和 允许您专注于特定于您的应用的逻辑。
如何使用 Volley 创建通用 GET/POST 方法。
创建应用程序类
Android 中的 Application 类是 Android 中的基类 包含所有其他组件(例如活动和服务)的应用
public class MyApplication extends Application
public static final String TAG = MyApplication.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
@Override
public void onCreate()
super.onCreate();
mInstance = this;
public static synchronized MyApplication getInstance()
return mInstance;
public RequestQueue getRequestQueue()
if (mRequestQueue == null)
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
return mRequestQueue;
public <T> void addToRequestQueue(Request<T> req, String tag)
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
public <T> void addToRequestQueue(Request<T> req)
req.setTag(TAG);
getRequestQueue().add(req);
public void cancelPendingRequests(Object tag)
if (mRequestQueue != null)
mRequestQueue.cancelAll(tag);
确保添加此 Manifest 部分。
<application
.....
android:name=".MyApplication"
>
现在,您需要创建 Singleton 类。
单例模式说只定义一个只有一个的类 实例并提供对其的全局访问点。
public class MySingleton
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private static Context mCtx;
private MySingleton(Context context)
mCtx = context;
mRequestQueue = getRequestQueue();
public static synchronized MySingleton getInstance(Context context)
if (mInstance == null)
mInstance = new MySingleton(context);
return mInstance;
public RequestQueue getRequestQueue()
if (mRequestQueue == null)
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
return mRequestQueue;
public <T> void addToRequestQueue(Request<T> req)
getRequestQueue().add(req);
现在通用类
public class VolleyUtils
public static void GET_METHOD(Context context, String url, final VolleyResponseListener listener)
// Initialize a new StringRequest
StringRequest stringRequest = new StringRequest(
Request.Method.GET,
url,
new Response.Listener<String>()
@Override
public void onResponse(String response)
listener.onResponse(response);
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
listener.onError(error.toString());
)
;
// Access the RequestQueue through singleton class.
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
public static void POST_METHOD(Context context, String url,final Map<String,String> getParams, final VolleyResponseListener listener)
// Initialize a new StringRequest
StringRequest stringRequest = new StringRequest(
Request.Method.POST,
url,
new Response.Listener<String>()
@Override
public void onResponse(String response)
listener.onResponse(response);
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
listener.onError(error.toString());
)
/**
* Passing some request headers
* */
@Override
public Map<String, String> getHeaders() throws AuthFailureError
HashMap<String, String> headers = new HashMap<String, String>();
getParams.put("Content-Type", "application/json; charset=utf-8");
return headers;
;
// Access the RequestQueue through singleton class.
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
现在您应该创建 Interface 。
一个类实现一个接口,从而继承抽象 接口的方法。
/**
* Created by Intellij Amiyo on 10-06-2017.
* Please follow standard Java coding conventions.
* http://source.android.com/source/code-style.html
*/
public interface VolleyResponseListener
void onError(String message);
void onResponse(Object response);
如何打电话
public void _loadAPI()
//GET
String URL_GET = "";
VolleyUtils.GET_METHOD(MainActivity.this, URL_GET, new VolleyResponseListener()
@Override
public void onError(String message)
System.out.println("Error" + message);
@Override
public void onResponse(Object response)
System.out.println("SUCCESS" + response);
);
//POST
String URL_POST=" ";
VolleyUtils.POST_METHOD(MainActivity.this, URL_POST,getParams(), new VolleyResponseListener()
@Override
public void onError(String message)
System.out.println("Error" + message);
@Override
public void onResponse(Object response)
System.out.println("SUCCESS" + response);
);
public Map<String,String> getParams()
Map<String, String> params = new HashMap<String, String>();
params.put("YOUR_KEY", "VALUE");
return params;
对于演示,您应该下载Volley-Common-Method
【讨论】:
【参考方案3】:如果您遵循Android Volley - How to isolate requests in another class 中的一般示例,(包括有关单例的东西)并寻找解析部分(或者,如何实际使用您收到的对象),那么这是(再次非常笼统的)添加
假设你有一个 Json 对象进来,看起来有点像这样:
“用户”: ["username":"Jon Doe","userid":83, "username":"Jane Doe",userid":84]
我们的用户对象看起来像这样:
public class User
String username;
int userid;
public String getName()
return username;
public int getId()
return userid;
重要提示:使用 Gson 时(稍后会看到),对象 字段应根据您在 Json 中获得的参数命名,这 某种反射是解析的工作方式。
然后,请求本身看起来像这样 (注意监听器回调返回一个
List<User>
对象返回给调用者,稍后你会看到):
public class NetworkManager
//... other stuff
public void getUsers(final SomeCustomListener<List<User>> listener)
final String URL = "http://httpbin.org/ip";
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>()
@Override
public void onResponse(String response)
Log.d(TAG + ": ", "getUsers Response: " + response);
List<User> users = MyJsonParser.getListObjects(response, "$.users[*]", User.class);
if(null != users)
listener.getResult(users);
,
new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
if (null != error.networkResponse)
Log.d(TAG + ": ", "Error Response code: " + error.networkResponse.statusCode);
listener.getResult(null);
);
requestQueue.add(request);
// ... other stuff
您现在需要的是解析 Json 字符串的类,即对象列表,在此示例中我使用 Gson(再次 - 这是一个通用示例,根据您的需要更改和重新排序内容,您可能还可以再优化一下——这只是为了解释):
public class MyJsonParser
//... other stuff
public static <T> List<T> getListObjects(String json_text, String json_path, Class<T> c)
Gson gson = new Gson();
try
List<T> parsed_list = new ArrayList<>();
List<Object> nodes = JsonPath.read(json_text, json_path);
for (Object node : nodes)
parsed_list.add(gson.fromJson(node.toString(), c));
return (parsed_list);
catch (Exception e)
return (new ArrayList<>());
//... other stuff
所以,在我们有了所有这些(以及前面提到的 SO 问题中的以下内容)之后,您所说的您正在寻找的是工作代码中的回调,这可以通过以下几种方式实现:
直截了当:
只需调用该方法并在那里覆盖它的回调,例如:
public class SomeClass
private List<User> mUsers;
private void someMethod()
// ... method does some stuff
NetworkManager.getInstance().getUsers(new SomeCustomListener<List<User>>()
@Override
public void getResult(List<User> all_users)
if (null != allUsers)
mUsers = allUsers;
// ... do other stuff with our info
);
// ... method does some more stuff
或者,以间接方式(考虑时间、内存消耗等),您可以将获得的信息保存在同一个 Singelton(或另一个容器)中,并创建一个 get 方法,稍后再获取对象(看起来更漂亮)
记住:触发请求之前(考虑到响应的延迟),因为这些回调的性质取决于可能延迟的响应。
它看起来像这样:
private List<User> mUsers;
private void someMethod()
// ... method does some stuff
mUsers = NetworkManager.getInstance().getUsersObject();
// ... method does some more stuff
完全不同的选择是考虑使用Retrofit,它为您进行解析,使用注释,并且据说速度更快,这可能是您正在寻找的(对于流线型外观) - 我会阅读基准,尤其是在新的 2.0 版本问世之后。
希望这会有所帮助(虽然有点晚了)! :)
【讨论】:
以上是关于如何为跨类 Volley 方法调用创建适当的 Volley 侦听器的主要内容,如果未能解决你的问题,请参考以下文章
如何为 Android M 及更高版本的 Volley 编写 OkHttp3 堆栈?