zoukankan      html  css  js  c++  java
  • Android应用中网络请求库Volley的使用

    上文,这次来说一下如何使用Volley,会给出一些范例,和原理

    Volley使用 StringRequest

    // 初始化一个请求队列,RequestQueue是volley库的类
    RequestQueue queue = Volley.newRequestQueue(this);
    String url ="http://www.baidu.com";
    //定义一个字符串型请求队列,需要传递4个参数分别是:url, 请求的方式(get, post..),响应成功的处理函数匿名对象, 相应出错时候的处理函数匿名对象
    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            // Display the first 500 characters of the response string.
    mTextView.setText("Response is: "+ response.substring(0,500));
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            mTextView.setText("That didn't work!");
        }
    });
    //添加到请求队列中,默认就开始了网络请求
    queue.add(stringRequest);

    按照Volley的设计规则,程序要只要创建一个RequestQueue,并传递一个Request对象行了。RequestQueue维护这一些正在访问网络的线程的运行,读写缓存,获取网络请求的返回等事务。Request对象会再收到数据后进行解析,而RequestQueue还会负责将解析过的数据返回给主线程(UI线程),以便于你将数据在UI控件中展示等。

    要使用Volley,必须在应用的Menifest文件中声明android.permission.INTERNET的权限。

    Volley发送网络的过程解析

    要想在代码中获取一个RequestQueue,默认可以使用Volley.newRequestQueue方法来完成,如上述代码所示。当然你也可以自己定义一个你自己的RequestQueue。从上面的代码看出,当Request对象创建好后,你只要调用RequestQueue的add()方法(参数就是Request对象)就能将这个网络请求发出。当add方法调用后,Volley会自动创建一个缓存处理线程和一个网络请求线程池,Volley会先判断你发送网络请求是否曾经存在于缓存中,若已经存在,那么缓存处理线程会对发出请求进行处理并返回结果(中间没有任何网络交互)。如果你发送的网络请求在缓存没有找到,那么这个请求会被放在网络请求队列中,网络请求线程池中会逐个从网络请求队列中获取请求内容,通过HTTP发生网络请求事务,返回的结果由Volley返回给主线程。

    Volley取消网络请求操作

    Volley库可以在代码中使用RequestQueue中的cancelAll()方法完成。比如,每个Request子类都有个setTag(Object obj)的方法,可以将每个tag设置为一类请求。比如你在一个Activity中的所有Request都用this(Activity的this就是该activity实例)作为setTag的参数,你可以随时随地调用RequestQueue的cancelAll(Object obj)方法,传递this作为obj的实参,这样这个activity的所有网络请求都被取消了。当然也可以传递任意的字符串类型的参数(最好有意义的字符串),代码实例:

    public static final String TAG = "MyTag";
    StringRequest stringRequest; // Assume this exists.
    RequestQueue mRequestQueue;  // Assume this exists.
    
    // 给Request设置tag进行分来
    stringRequest.setTag(TAG);
    
    mRequestQueue.add(stringRequest);

    取消网络请求比较好的途径是放在activity的onStop方法中(也可以是任何地方,这里是惯例),如下

    @Override
    protected void onStop () {
        super.onStop();
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(TAG);
        }
    }

    另外需要注意的是,Request的响应处理函数(Response.Listener和Response.ErrorListener,见上)此时不会被调用。

    如何在Request中设置Htpp请求的Header, Body?

    要想设置request中的http请求中的header, boday内容可以重载getHeader方法

    StringRequest request = new StringRequest(Request.Method.POST, "www.yoururl.com", new Response.Listener<String>() {
        @Override
        public void onResponse(String s) {
    
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
    
        }
    }){
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            HashMap<String, String> map = new HashMap<>();
            Map<String, String>  params = new HashMap<String, String>();
            params.put("User-Agent", "Nintendo Gameboy");
            params.put("Accept-Language", "fr");
            params.put("Authorization", "Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b");
    
            return params;
        }
    };

    对你有用的话,就点个赞吧, :)

    2015-8-3编辑加入新内容

    使用JsonOjectRequest来提交和获取JSONObject格式的请求,不需要设置getParams和getBody(), 后台是Django restful API. 使用下列的代码,灰常简单.

        
    //In MyFragment.java
    HashMap<String, String> data = new HashMap<>();
    data.put("username", "ppppppppp");
    data.put("password", "a");
    data.put("mobile_phone", "221212");

    NetworkUtil.registerUser2(data);

    //NetworkUtil.java
    public static JSONObject registerUser2(final HashMap<String, String> data) { JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, formAPI(API_MYUSER), new JSONObject(data), new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject responseStr) { System.out.println(responseStr); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { LogUtils.d(TAG, volleyError.getMessage()); } }); AppController.getInstance().addToRequestQueue(jsonObjectRequest); return null; }

    应用运行后,在Django后台打印的Log

    [03/Aug/2015 23:23:43]"POST /myuser/ HTTP/1.1" 201 190
    {u'username': u'ppppppppp', u'password': u'a', u'mobile_phone': u'221212'}
    [03/Aug/2015 23:24:59]"POST /myuser/ HTTP/1.1" 201 192

    这里有篇引用, http://stackoverflow.com/questions/19837820/volley-jsonobjectrequest-post-request-not-working

    使用StringRequest做Post提交的时候,会想当然的将要传入的数据放在getParams()函数中,但每次运行都是得到下面的错误, 意思是Bad Request, 应该是参数组成有误:

    02-12 21:42:54.774: E/Volley(19215): [46574] BasicNetwork.performRequest: Unexpected response code 400 for http://somename/token/

    而用上面的JsonObjectRequest做提交,问题解决, 但这Volley提供的StringRequest方法,让人想当然的会这么使用,在StackOverflow上有N多人碰到上面的错误,结果都切换成JsonObjectRequest.

    另外使用JsonObjectRequest的一个典型的错误是使用下列代码,

     RequestQueue queue = MyVolley.getRequestQueue();
            JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,SPHERE_URL,null,
                    new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            System.out.println(response);
                            hideProgressDialog();
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                          hideProgressDialog();
                        }
                    }) {
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("id","1");
                    params.put("name", "myname");
                    return params;
                };
            };
            queue.add(jsObjRequest);

    这种做法无法正确提交请求!

  • 相关阅读:
    第27章 结构型模式大PK
    第26章 创建型模式大PK
    Linux下C/C++代码调用PHP代码(转)
    php 5.2.17 升级到5.3.29
    PHP安全之register_globals (转)
    注意字符串的strlen与sizeof的差别
    嵌入式串口传送汉字乱码
    字符设备驱动模块与测试代码编写(转)
    字符设备之register_chrdev与register_chrdev_region(转)
    I2C子系统驱动框架及应用 (转)
  • 原文地址:https://www.cnblogs.com/jimmytech/p/4693185.html
Copyright © 2011-2022 走看看