qtfreet00 发表于 2016-1-18 17:31

【笔记】还在用HttpUrlConnection?了解下简单高效的两个网络库吧-Volley,Okhttp

本帖最后由 世事繁华皆成空 于 2016-1-18 17:38 编辑

在安卓4.0以后,Android已不允许在主线程中请求网络,对于这类可能会耗时的操作,放在主线程中运行的话会给用户带来非常不好的用户体验,并且在安卓5.0以后,Google彻底抛弃了Apache的HttpClient网络请求方式,并推出了一个轻量级的Volley网络框架

一个常见的网络请求方式,以Gankio妹纸为例:
      public static void httpUrlConnectionGet() {
                new Thread(new Runnable() {//新起一个线程,把网络请求放在这里

                        @Override
                        public void run() {
                              InputStream in = null;
                              BufferedReader br = null;
                              HttpURLConnection conn = null;
                              URL url = null;
                              try {
                                        String en = URLEncoder.encode("福利", "UTF-8");             //对请求的网址进行url编码,很多网站对中文的识别很不好,不进行编码的话很有可能无法获取数据
                                        url = new URL("http://gank.avosapps.com/api/data/" + en + "/10/1");
                                        conn = (HttpURLConnection) url.openConnection();            
                                        conn.setRequestMethod("GET");
                                        conn.setConnectTimeout(5000);             //设置请求方式和超时时长
                                        in = conn.getInputStream();         //获取请求到的数据流
                                        br = new BufferedReader(new InputStreamReader(in, "UTF-8"));         //把流转为bufferReader
                                        StringBuffer sb = new StringBuffer();
                                        String line = "";
                                        while ((line = br.readLine()) != null) {
                                                sb.append(line);                        //循环读取
                                        }
                                        System.out.println(sb.toString());
                                        br.close();
                                        in.close();

                              } catch (MalformedURLException e) {
                                        e.printStackTrace();
                              } catch (IOException e) {
                                        e.printStackTrace();
                              } finally {
                                        if (conn != null) {
                                                conn.disconnect();
                                        }
                              }

                        }
                }).start();                  //启动线程
      }

上面就是一个最简单的网络请求方式,接下来会在控制窗口输出返回的数据



数据已经完美的获取到了,这是一段json数据,接下来的事就是解析json标签了,这个本文不做演示


这里可以看到上述的代码只是单纯的完成一个访问网络的操作,却写了那么多代码,还要注意关闭连接等等操作,虽然也是目前的主流网络请求框架,但对于我们个人来说,未免还是有些复杂了

Volley是2013年Google在I/O大会上发布的一款轻量级网络请求框架,一个简单的例子

Volley主要是基于队列进行管理的,那么就需要一个全局管理的方法,一个最简单的方式

public class App extends Application {
    public static RequestQueue requestQueue;

    @Override
    public void onCreate() {
      super.onCreate();
      requestQueue = Volley.newRequestQueue(this);
    }
}


声明一个全局静态变量requestQueue,并在App初始化的进行实例化,接下来我们就可以在代码中进行使用了


    public void VolleyTest() {
      StringRequest stringRequest = new StringRequest("http://gank.avosapps.com/api/data/%E7%A6%8F%E5%88%A9/10/1", new Response.Listener<String>() {

//这里只需要简单的定义请求的网址,正确返回数据的监听器和失败的监听器
            @Override
            public void onResponse(String s) {
Log.e("TAG", s.toString());            //正确访问后就可以在这里获取到数据

            }
      }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
      });
      stringRequest.setTag("qtfreet");
      App.requestQueue.add(stringRequest);   //设置请求的TAG,将该请求添加到队列中即可,设置TAG的好处就是方便之后的管理

    }

Volley是基于异步请求的,所以你完全不用担心在请求过程中会堵塞主线程,但我们发现,上述访问返回的数据是个json格式的数据,不妨我们直接以json返回即可

    public void VolleyTest() {
      JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "", new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                Log.e("TAG",jsonObject.toString());
            }
      }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {

            }
      });
      jsonObjectRequest.setTag("qtfreet");
      App.requestQueue.add(jsonObjectRequest);

    }

这里返回的数据就直接格式化为json了,接下来就跟上面一样,解析json数据获取自己想要的内容即可

我们可以发现,Volley的请求方式要比HttpUrlConnection简单的多,而且高效,但是Volley也有自己不足的地方,对于大型数据,Volley就力不从心了,Volley无法将数据以流的形式返回,那就说明,Volley无法用来进行下载操作,一般的,我们用他来加载文字数据和图片数据

Okhttp:

Okhttp是著名开源组织square的开发的一款网络框架,优势在于

支持SPDY,允许连接同一主机的所有请求分享一个socket。 如果SPDY不可用,会使用连接池减少请求延迟。 使用GZIP压缩下载内容,且压缩操作对用户是透明的。 利用响应缓存来避免重复的网络请求。 当网络出现问题的时候,OKHttp会依然有效,它将从常见的连接问题当中恢复。 如果你的服务端有多个IP地址,当第一个地址连接失败时,OKHttp会尝试连接其他的地址,这对IPV4和IPV6以及寄宿在多个数据中心的服务而言,是非常有必要的。
因此使用 OkHttp 作为替代是好的选择.
而且常规方法下,Okhttp的使用难度几乎和Volley相同,非常简单

      public static void OkhttpTest() {
                OkHttpClient ok = new OkHttpClient();   //实例化OkHttpClient
                Request req = new Request.Builder().url("http://gank.avosapps.com/api/data/福利/10/1").build();//创建请求队列
                ok.newCall(req).enqueue(new Callback() {                  //创建一个新的Call来请求数据

                        @Override
                        public void onResponse(Response arg0) throws IOException {
                              System.out.println(arg0.body().string());
                        }

                        @Override
                        public void onFailure(Request arg0, IOException arg1) {
                        }
                });
      }

这里是直接可以返回数据了,当然还有一种写法

      public static String OkhttpTest() throws IOException {
                OkHttpClient ok = new OkHttpClient();
                Request req = new Request.Builder().url("http://gank.avosapps.com/api/data/福利/10/1").build();
                Response res = ok.newCall(req).execute();
                if (res.isSuccessful()) {
                        return res.body().string();
                }
                return null;
      }

两种方式都是一样的,而且Okhttp支持数据流操作,这相较于Volley是有绝对的优势,如上的res获取他的流就是res.body().byteStream(),但这并不能就把Volley给一票否决了

两者都有各自的优势和缺点,两者兼用才是王道

项目地址:
volley:https://github.com/mcxiaoke/android-volley

Okhttp:https://github.com/square/okhttp

最后补上gankio几张妹纸图








fan0424 发表于 2016-1-18 20:21

用xutils也挺好用的   还有楼主上面第一个代码设置请求方式与时长后是不是应该接收下响应码来判断一下呢?

iCloud 发表于 2016-1-18 17:35

前排坐下了、

就爱玩玩 发表于 2016-1-18 17:48

拿水杯的妹子我喜欢

wqh171941 发表于 2016-1-18 18:10

膜拜java大神,汝便是吾的目标,吾必good good study, day day up,与汝们为一列

动次丶打次 发表于 2016-1-18 18:22

膜拜大神

easlandll 发表于 2016-1-18 18:41

妹子,才是重点!!

2217936322 发表于 2016-1-18 18:42

镇楼妹子收走 哈哈哈

manbajie 发表于 2016-1-18 18:51

涨姿势了

方妍心 发表于 2016-1-18 20:08

繁大这是准备出新东西的节奏{:301_1003:}偷偷跟我说下吧{:301_997:}
页: [1] 2
查看完整版本: 【笔记】还在用HttpUrlConnection?了解下简单高效的两个网络库吧-Volley,Okhttp