繁体   English   中英

如何为跨类Volley方法调用创建一个合适的Volley Listener

[英]How to create a proper Volley Listener for cross class Volley method calling

我的目标是从另一个班级调用Volley,这是一种非常简洁,模块化的方式,即:

            VolleyListener newListener = new VolleyListener();
            VolleySingleton.getsInstance().somePostRequestReturningString(getApplicationContext(), newListener);
            JSONObject data = newListener.getResponse();

但是在让侦听器部分工作以便能够从诸如的方法访问结果数据方面遇到了麻烦

newListener.getResponse();

本网站上有一些问题,通常概述了如何设置来自另一个类的凌空调用,例如: Android Volley - 如何隔离另一个类中的请求 我已经成功地让方法调用工作,但是现在将这些数据放入当前类中以便使用已经造成了麻烦。

我在我的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调用和数据检索,尤其是如何正确构建回调?

根据您的要求,我建议您参考我的以下解决方案,希望它清楚有用:

首先是界面

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:如何从使用Volley的方法返回异步JSONObject?

POST请求Json文件传递String并等待响应Volley

Android / Java:如何在一个方法中延迟返回

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类。

Singleton Pattern表示只需定义一个只有一个实例的类,并提供对它的全局访问点。

   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);
    }
}

现在你应该创建接口

类实现接口,从而继承接口的抽象方法。

 /**
 * 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

如果你按照 Android Volley 的一般例子 - 如何隔离另一个类中的请求 ,(包括关于单例东西的东西)和寻找解析部分(或者,如何实际使用你收到的对象),那么这就是(再次非常一般)补充

假设你有一个Json对象,看起来有点像这样:

{“users”:[{“username”:“Jon Doe”,“userid”:83},{“username”:“Jane Doe”,userid“:84}]}

我们的User对象看起来像这样:

public class User
{
 String username;
 int userid;

 public String getName()
 {
 return username;
 }

 public int getId()
 {
 return userid;
 }
}

重要提示:使用Gson时(稍后会看到),对象字段应根据您在Json中获得的params命名,这种反射是解析的工作方式。

然后,请求本身看起来像这样(注意听众回调返回一个

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版本问世以来。

希望这有助于(虽然有点晚)! :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM