网络框架之volley

一、简介

1.下载和视频

1.下载地址:https://github.com/mcxiaoke/android-volley
2.volley视频:http://www.youtube.com/watch?v=yhv8l9F44qo&feature=player_embedded
3.它是谷歌在2013年I/O大会上提出来的一套解决 Android与服务器端进行通信的框架

2.android提供的两种方式来进行HTTP通信
    HttpClicent 建议在2.3之前的版本使用,bug少
    HttpUrlConnection建议2.3以后使用,他api简单,体积小,非常适合移动项目这种轻量级的项目,压缩和缓存机制可以有效的减少网络访问的流量,在提升速度和省电方面也起到了很大的作用
    在 Froyo(2.2) 之前,HttpURLConnection 有个重大 Bug,调用 close() 函数会影响连接池,导致连接复用失效,所以在 Froyo 之前使用 HttpURLConnection 需要关闭 keepAlive

3.Google推荐的用法
如果一个App需要频繁的网络通信的话,建立多个RequestQueue是件很奇怪的事儿(谁会因为临时有飞机要在海上起飞就去新建一艘航母呢,这得多有钱啊),所以Google推荐我们只实例化一个RequestQueue来应付频繁的Http通信,当然,要保证队列的寿命和App一样长。如何实现呢?Google又说了,不推荐在App的Application.onCretae()方法中实例化一个RequestQueue(不过确实是个简单的方法哈),最好是建立一个单例模式的类,并把所有我们需要用到的Volley的瓶瓶罐罐都放进去,这样显得更模块化。

4.缺点:不适合大文件的上传和下载

二、功能
    json数据加载,图片异步下载
    缓存功能
    和Activity的生命周期联动(Activity结束以后可以取消所有网络请求)
    多级别任务取消
    网络请求排序

三、Http请求
    Request请求
        1.StringRequest(重点)
        2.JsonObjectRequest(了解)
        3.JsonArrayRequest(了解)
        4.自定义Request(了解)
    使用方式
        第一步创建请求队列
            这里拿到的RequestQueue是一个请求队列对象,它可以缓存所有的HTTP请求,然后按照一定的算法并发地发出这些请求。RequestQueue内部的设计就是非常合适高并发的,因此我们不必为每一次HTTP请求都创建一个RequestQueue对象,这是非常浪费资源的,建议使用封装单利模式
            RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
        第二步创建请求
            GET------>请求:StringRequest request = new StringRequest(url, listener, errorListener)
                String url 加载数据网址
                Listener<String> listener(接口) 数据加载成功回调方法
                ErrorListener errorListener(接口) 数据加载失败回调方法
        POST请求
                当发出POST请求的时候,Volley会尝试调用StringRequest的父类——Request中的getParams()方法来获取POST参数
                在StringRequest的匿名类中重写getParams()方法,在这里设置POST参数就可以了
    StringRequest stringRequest = new StringRequest(Method.POST, url,  listener, errorListener) {
    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        Map<String, String> map = new HashMap<String, String>();
        map.put("params1", "value1");
        map.put("params2", "value2");
        return map;
    }
};
        第三步设置tag
            request.setTag(this)
                Object object 设置取消的标识
                一般使用Activity或者fragment作为标识
        第四步添加进请求队列
            queue.addRequest(request)
        第五步取消请求
            重写Activity或者fragment的 onStop()方法
                @Override
    protected void onStop() {
        super.onStop();
        queue.cancelAll(this);
    }

        其他
            设置请求(HTTP headers)

                有时候需要给HTTP请求添加额外的头信息,一个常用的例子是添加 “Authorization”到HTTP 请求的头信息。Volley请求类提供了一个 getHeaers()的方法,重载这个方法可以自定义HTTP 的头信息。
                    JsonObjectRequest request = new JsonObjectRequest(URL, new JSONObject(params),
           new Response.Listener<JSONObject>() {
               @Override
               public void onResponse(JSONObject response) {
                   // handle response
               }
           }, new Response.ErrorListener() {
               @Override
               public void onErrorResponse(VolleyError error) {
                   // handle error                        
               }
           }) {

       @Override
       public Map<String, String> getHeaders() throws AuthFailureError {
           HashMap<String, String> headers = new HashMap<String, String>();
           headers.put("CUSTOM_HEADER", "qian'feng");
           headers.put("ANOTHER_CUSTOM_HEADER", "qianfeng");
           return headers;
       }
   };
            使用Cookies
                Volley中没有直接的API来设置cookies,Volley的设计理念就是提供干净、简洁的API来实现RESTful HTTP请求,不提供设置cookies是合理的。          下面是修改后的ApplicationController类,这个类修改了getRequestQueue()方法,包含了 设置cookie方法,这些修改还是有些粗糙
                private DefaultHttpClient mHttpClient;
public RequestQueue getRequestQueue() {
    // lazy initialize the request queue, the queue instance will be
    // created when it is accessed for the first time
    if (mRequestQueue == null) {
        // Create an instance of the Http client.
        // We need this in order to access the cookie store
        mHttpClient = new DefaultHttpClient();
        // create the request queue
        mRequestQueue = Volley.newRequestQueue(this, new HttpClientStack(mHttpClient));
    }
    return mRequestQueue;
}

/**
 * Method to set a cookie
 */
public void setCookie() {
    CookieStore cs = mHttpClient.getCookieStore();
    // create a cookie
    cs.addCookie(new BasicClientCookie2("cookie", "spooky"));
}


// add the cookie before adding the request to the queue
setCookie();

// add the request to the queue
mRequestQueue.add(request);
                Cookies用在程序设计中是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术。当你浏览某网站时,由Web服务器置于你硬盘上的一个非常小的文本文件,它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。当你再次来到该网站时,网站通过读取Cookies,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。从本质上讲,它可以看作是你的身份证
    类似第三方开源库
        1.android-async-http
            它把HTTP所有的通信细节全部封装在了内部,我们只需要简单调用几行代码就可以完成通信操作了,避免重复代码
            1.处理异步Http请求,并通过匿名内部类处理回调结果
            2.Http请求均位于非UI线程,不会阻塞UI操作
            3.通过线程池处理并发请求
            4.处理文件上传、下载
            5.响应结果自动打包JSON格式
            6.二进制文件下载(如图片)
            7.自动处理连接断开时请求重连
            8.持久化存储cooki,将cooki保存到你应用的SharedPreferences
        2.android-lite-http   https://github.com/litesuits/android-lite-http
        3.okhttp https://github.com/square/okhttp

四、图片异步下载
    1.Volley-image
        ImageRequest(了解)
        ImageLoader(重点)
        NetworkImageView(重点)
        4.图片内存缓存处理(Lrucache)
    2.使用方式
        ImageRequest
            参照Request的使用方式
        ImageLoader(代码参照案例)
            创建一个RequestQueue对象
            创建一个ImageLoader对象
            获取一个ImageListener对象
            调用ImageLoader的get()方法加载网络上的图片
         NetworkImageView(代码参照案例)
            创建一个RequestQueue对象
            创建一个ImageLoader对象
            在布局文件中添加一个NetworkImageView控件。
            在代码中获取该控件的实例。
            设置要加载的图片地址。

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private LinearLayout mOperation;
    private TextView mContent;
    private ImageView mImage;
    private RequestQueue mQueue;
    LruCache<String,Bitmap> lruCache = new LruCache<>(1024*1025*5);
    private NetworkImageView mImage2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mOperation = (LinearLayout)findViewById(R.id.operation);
        mContent = (TextView)findViewById(R.id.text);
        mImage = (ImageView)findViewById(R.id.image);
        mImage2 = (NetworkImageView)findViewById(R.id.image2);

        setAllClick();

        //1、创建请求队列
        mQueue = Volley.newRequestQueue(this);

    }

    private void loadImage() {
        String url ="http://fmn.rrfmn.com/fmn060/20150204/0425/large_JV8E_4c30000177a5125f.jpg";
        //2、创建loader 缓存
        ImageLoader.ImageCache cache =new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return lruCache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                lruCache.put(url,bitmap);
            }
        };
        //1、创建ImageLoader
        ImageLoader loader = new ImageLoader(mQueue,cache);
        //3、加载图片
        loader.get(url,ImageLoader.getImageListener(mImage,R.mipmap.ic_launcher,R.mipmap.ic_launcher));
        //4、netWorkImageView
        mImage2.setImageUrl("http://img5.imgtn.bdimg.com/it/u=2685634614,3437522115&fm=21&gp=0.jpg",loader);
    }

    private void setAllClick() {
        /**
         * StringRequest
         */
        mOperation.getChildAt(0).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                stringRequestGet();
                stringRequestPost();
            }
        });
        /**
         * JsonObjectRequest
         */
        mOperation.getChildAt(1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                jsonObjRequest();
            }
        });
        /**
         * MyRequest
         */
        mOperation.getChildAt(2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                objectRequest();
            }
        });
        /**
         * ImageLoad
         */
        mOperation.getChildAt(3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadImage();
            }
        });

    }



    private void objectRequest(){
        String url = "http://139.129.19.51/story/index.php/home/Interface/login";
        ObjectRequest<LoginResult> request = new ObjectRequest<LoginResult>(Request.Method.POST, url, LoginResult.class, new Response.Listener<LoginResult>() {
            @Override
            public void onResponse(LoginResult response) {
                if(response!=null){
                    mContent.setText(response.getMsg());
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        }){
            /**
             * 注意::::!!!!! 参数
             * @return
             * @throws AuthFailureError
             */
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                HashMap<String,String> params = new HashMap<>();
                params.put("username","admin");
                params.put("password","123456");
                return params;
            }
        };

        mQueue.add(request);
    }

    /**
     * String加载GET
     */
    private void stringRequestGet() {

        //2、创建请求

        String url = "http://www.baidu.com";
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                //回调主线程
                mContent.setText(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        //选择性,添加标记,用于取消网络
        request.setTag(this);
        //3、添加请求
        mQueue.add(request);
    }

    /**
     * String加载POST
     */
    private void stringRequestPost() {

        //2、创建请求

        String url = "http://139.129.19.51/story/index.php/home/Interface/login";
        StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                //回调主线程
                mContent.setText(response);
                Gson gson  = new Gson();
                LoginResult loginResult = gson.fromJson(response, LoginResult.class);
                Log.i(TAG,loginResult.getData().getNickname());
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG,error.getMessage());
            }
        }){
            /**
             * 注意::::!!!!! 参数
             * @return
             * @throws AuthFailureError
             */
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                HashMap<String,String> params = new HashMap<>();
                params.put("username","admin");
                params.put("password","123456");
                return params;
            }
        };
        //选择性,添加标记,用于取消网络
        request.setTag(this);
        //3、添加请求
        mQueue.add(request);
    }

    /**
     * 提交JSON 请求
     */
    private void jsonObjRequest(){
        String url = "http://139.129.19.51/story/index.php/home/Interface/loginJson";

        //注意传参 为 json串
        HashMap<String,String> params = new HashMap<>();
        params.put("username","admin");
        params.put("password","123456");
        JSONObject jsonObj = new JSONObject(params);
        String body  =jsonObj.toString();
        Log.i(TAG,body);
        JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, body, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                    if(response!=null){
                        int result = response.optInt("result");
                        if(result==1){
                            String msg = response.optString("msg");
                            mContent.setText(msg);
                        }else{
                            mContent.setText("登录失败!!!!");
                        }
                    }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });

        request.setTag(this);

        mQueue.add(request);
    }

    @Override
    protected void onDestroy() {
        //取消网络请求
        mQueue.cancelAll(this);
        super.onDestroy();
    }
}
Gson

import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;

import java.io.UnsupportedEncodingException;

/**
 * Created by keven on 16/3/14.
 */
public class ObjectRequest<T> extends Request<T> {

    private final Response.Listener success;    //成功监听
    private final Class<T> cls;                 //传递类型,通过类型转换返回的参数

    public ObjectRequest(int method, String url, Class<T> cls, Response.Listener success, Response.ErrorListener listener) {
        super(method, url, listener);
        this.success = success;
        this.cls = cls;
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {

        String  result = null;
        try {
            //处理返回的数据
            result = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            //Gson 转换 类型
            Gson gson = new Gson();
            T t = gson.fromJson(result, cls);
            return Response.success(t,HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new VolleyError(e));
        }
    }

    @Override
    protected void deliverResponse(T response) {
        if(success!=null){
            success.onResponse(response);
        }
    }
}

bean就不贴了

 /**
     * result : 1
     * msg : 登录成功
     * data : {"id":"467","username":"admin","userpass":"MTRlMWI2MDBiMWZkNTc5ZjQ3NDMzYjg4ZThkODUyOTE=","usersex":"0","useremail":"sniper@dota.com","nickname":"holy maria","birthday":"1989-09-09","portrait":"20150909/55efa0ec0ec6a.jpg","signature":null}
     */


    类似第三方开源库
        Universal-Image-Loader
  https://github.com/nostra13/Android-Universal-Image-Loader
            1.多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
            2.支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
            3.支持图片的内存缓存,文件系统缓存或者SD卡缓存
            4.支持图片下载过程的监听
           5. 根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
           6. 较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
            7.提供在较慢的网络下对图片进行加载
        fresco   https://github.com/facebook/fresco
        picasso   https://github.com/square/picasso


Volley是一个优秀的安卓开源网络访问工具,这里包含了volley jar包和源码,版本是2015.07.28的1.0.18版本。更多资料可以参见volley的github地址: https://github.com/mcxiaoke/android-volley 1.0.18 2015.07.28 merge upstream, process response bodies only when present tweak getCacheKey(), using method and original url, fix #67 #78 add RedirectError, wrong exception for http 301 and 302, fix #51 make NetworkResponse Serializable, fix #53 create NetworkError using IOException, not using null response 1.0.17 2015.07.13 merge upstream, stop logging slow requests outside of debug logs merge pr #64, fix leaking the last request object 1.0.16 2015.05.18 fix duplicate retry, change DEFAULT_MAX_RETRIES to 0 merge pr, fix NegativeArraySizeException merge upstream, Use a BufferedOutputStream to read and write cache 1.0.15 2015.03.18 add two missing constructors for JsonArrayRequest and JsonObjectRequest add unique identifier for Request 1.0.14 2015.03.17 add more constructors for JsonArrayRequest and JsonObjectRequest update and fix gradle build, using new build.gradle 1.0.13 2015.03.16 merge pr, added constructor to JSONArrayRequest 1.0.12 2015.03.12 merge upstream, fix ImageLoader.getCacheKey() merge upstream, Fix broken DiskBasedCache merge upstream, Modify header parser to handle must-revalidate. 1.0.11 2015.03.03 merge upstream, Add a RequestFinishedListener to RequestQueue. merge upstream, Change the default character encoding for JSON responses to UTF-8 1.0.10 2014.12.30 merge upstream, Use the view size and scale type to restrict NIV requests. merge pr, Add a getImageURL method to NetworkImageView merge pr, Add the options of setting DiskBasedCache sizes in Volley.java 1.0.9 2014.11.26 merge upstream, Fix deprecation warnings (now errors in 0.14.4) w/ gradle. 1.0.8 2014.11.07 merge upstream, Metric for network time and getBackoffMultiplier() 1.0.7 2014.10.13 merge upstream, Add locale to HttpHeaderParserTest.rfc1123Date(long millis) merge upstream, Copy cache header for 304 response 1.0.6 2014.09.10 merge pr, fixed bug where Disk cache misses for redirects merge upstream, Fix crash/OOM in DiskBasedCache merge upstream, allow use of custom ImageRequests in ImageLoader 1.0.5 2014.06.18 merge upstream, Fixes bug in PATCH method. Sets the method before setting the body. update gradle and build tools version, fix build 1.0.4 2014.05.04 merge upstream, Guard against NullPointerException currently occurring in Volley when a Request is given a url whose host is null. 1.0.3 2014.04.01 merge upstream, ImageLoader: setError after null check 1.0.2 2014.02.28 merge upstream, Use the view size to restrict NIV requests. merge upstream, Fix generic type parameter for RequestQueue.add(Request) merge pr, added support for handling 301 and 302 http redirects using standalone deploy gradle build file and script 1.0.1 2014.02.13 add gradle build support, add readme, release using gradle 1.0.0 2014.01.03 create volley mirror at github, release first version
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值