java 如何为跨类 Volley 方法调用创建合适的 Volley Listener
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33535435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a proper Volley Listener for cross class Volley method calling
提问by Sauron
I aim to call Volley from another class in, a very succinct, modular way ie:
我的目标是从另一个班级中以一种非常简洁的模块化方式调用 Volley,即:
VolleyListener newListener = new VolleyListener();
VolleySingleton.getsInstance().somePostRequestReturningString(getApplicationContext(), newListener);
JSONObject data = newListener.getResponse();
But am having allot of trouble getting the listener portion to work so as to be able to access the resulting data from a method such as
但是我在让侦听器部分工作以便能够从诸如的方法访问结果数据时遇到了麻烦
newListener.getResponse();
There are a few questions on this site that generally outline how to set up a volley call from another class, such as: Android Volley - How to isolate requests in another class. I have had success getting the method call to work, but to now get that data into the present class for usage has caused trouble.
该站点上有几个问题,大致概述了如何设置来自另一个类的 volley 调用,例如:Android Volley - 如何隔离另一个类中的请求。我已经成功地使方法调用起作用,但现在将该数据放入当前类以供使用已经造成了麻烦。
I have the action within my VolleySingleton
class as:
我在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);
}
and within the listener class:
并在侦听器类中:
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;
}
};
}
}
How can I configure this to work and allow Volley calls and data retrieval from another class, particularly how to build callbacks correctly?
如何配置它以使其工作并允许从另一个类中进行 Volley 调用和数据检索,尤其是如何正确构建回调?
回答by BNK
For your requirement, I suggest you refer to my following solution, hope it's clear and helpful:
对于您的要求,我建议您参考我的以下解决方案,希望它清楚且有帮助:
First is the interface:
首先是界面:
public interface VolleyResponseListener {
void onError(String message);
void onResponse(Object response);
}
Then inside your helper class (I name it VolleyUtils
class):
然后在您的助手类中(我将其命名为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);
}
Then, inside your Activity classes, you can call like the following:
然后,在您的 Activity 类中,您可以像下面这样调用:
VolleyUtils.makeJsonObjectRequest(mContext, url, new VolleyResponseListener() {
@Override
public void onError(String message) {
}
@Override
public void onResponse(Object response) {
}
});
You can refer to the following questions for more information (as I told you yesterday):
您可以参考以下问题了解更多信息(正如我昨天告诉您的):
Android: How to return async JSONObject from method using Volley?
POST Request Json file passing String and wait for the response Volley
Android:如何使用 Volley 从方法中返回异步 JSONObject?
回答by IntelliJ Amiya
Volley excels at RPC-type operations used to populate a UI, such as fetching a page of search results as structured data. It integrates easily with any protocol and comes out of the box with support for raw strings, images, and JSON. By providing built-in support for the features you need, Volley frees you from writing boilerplate code and allows you to concentrate on the logic that is specific to your app.
Volley 擅长用于填充 UI 的 RPC 类型的操作,例如获取页面搜索结果作为结构化数据。它可以轻松与任何协议集成,开箱即用,支持原始字符串、图像和 JSON。通过为您需要的功能提供内置支持,Volley 将您从编写样板代码中解放出来,并让您专注于特定于您的应用程序的逻辑。
How to create Common GET/POSTMethod Using Volley.
如何使用Volley创建通用的 GET/POST方法。
Create a Application Class
创建应用程序类
The Application class in Android is the base class within an Android app that contains all other components such as activities and services
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);
}
}
}
Make Sure you add this ManifestSection .
确保你添加了这个ManifestSection 。
<application
.....
android:name=".MyApplication"
>
Now, You need to create SingletonClass .
现在,您需要创建SingletonClass 。
Singleton Pattern says that just define a class that has only one instance and provides a global point of access to it .
单例模式表示只需定义一个只有一个实例的类并提供对其的全局访问点。
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);
}
}
Now Common Class
现在普通班
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);
}
}
Now You should create Interface.
现在您应该创建Interface。
A class implements an interface, thereby inheriting the abstract methods of the 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);
}
How To Call
如何打电话
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;
}
For demo you should Download Volley-Common-Method
对于演示,您应该下载 Volley-Common-Method
回答by TommySM
If you followed the general examplefrom Android Volley - How to isolate requests in another class, (including the stuff regarding the singleton stuff) and looking for the parsing part (or, how to actually use the objects you receive), then this is the (again very general) addition
如果按照一般的例子来自Android的排球-如何在另一类分离的要求,(包括关于单身的东西的东西),寻找分析部分(或者,如何实际使用您收到的对象),那么这就是(再次非常一般)加法
say you have a Json object coming in, that looks somewhat like this :
假设你有一个 Json 对象进来,看起来有点像这样:
{"users": [{"username":"Jon Doe","userid":83}, {"username":"Jane Doe",userid":84}]}
{"users": [{"username":"Jon Doe","userid":83}, {"username":"Jane Doe",userid":84}]}
and our User object would look something like this:
我们的 User 对象看起来像这样:
public class User
{
String username;
int userid;
public String getName()
{
return username;
}
public int getId()
{
return userid;
}
}
Important: When working with Gson (you will see later), the object fields should be named according to params you get in the Json, this sort of reflection is how the parsing works.
重要提示:当使用 Gson 时(你会在后面看到),对象字段应该根据你在 Json 中得到的参数命名,这种反射就是解析的工作方式。
then, the request itself would look something like this (note the listener callback returning a
然后,请求本身看起来像这样(注意侦听器回调返回一个
List<User>
object back to the caller, you'll see later):
对象返回给调用者,稍后您会看到):
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
}
what you would need now is that class to parse the Json string, namely the object list, in this example I use Gson (again - this is a general example, change and reorder stuff according to your needs, you could probably also optimize this some more - it's just for the explanation):
你现在需要的是解析 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, after we have all this (and the following stuff from the pre-mentioned SO question), what you said you were looking for is the callback in your working code, well that can be achieved in a couple of ways:
因此,在我们完成所有这些(以及前面提到的 SO 问题中的以下内容)之后,您说您要寻找的是工作代码中的回调,这可以通过以下几种方式实现:
A straight forward way:
一个直接的方法:
just call the method and override it's callback right there, e.g:
只需调用该方法并在那里覆盖它的回调,例如:
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
}
}
Or, in an indirect way (considering the time, memory consumption, etc.), you can save the info you got in the same Singelton (or another container), and create a getmethod for it, and just get the object later (looks more slick)
或者,以一种间接的方式(考虑时间、内存消耗等),您可以将您获得的信息保存在同一个 Singelton(或另一个容器)中,并为其创建一个get方法,稍后再获取对象(看起来更光滑)
remember: fire the request before(considering the latency for the response), as the nature of these callbacks is to be dependent on the response which might be delayed.
请记住:之前触发请求(考虑响应的延迟),因为这些回调的性质取决于可能延迟的响应。
It would then look like this:
然后它看起来像这样:
private List<User> mUsers;
private void someMethod()
{
// ... method does some stuff
mUsers = NetworkManager.getInstance().getUsersObject();
// ... method does some more stuff
}
A different option entirely would be to consider using Retrofit, that does the parsing for you, uses annotations, and is supposedly a lot faster , that might be what you're looking for (for the streamlined look) - I would read up on benchmarks, especially since the new 2.0 version came out.
一个完全不同的选择是考虑使用Retrofit,它为你解析,使用注释,并且据说速度要快得多,这可能是你正在寻找的(为了简化的外观) - 我会阅读基准测试,尤其是新的 2.0 版本出来之后。
Hope this Helps (although somewhat late)! :)
希望这有帮助(虽然有点晚)!:)