Android网络请求框架比较学习

来源:互联网 发布:wind资讯金融终端 mac 编辑:程序博客网 时间:2024/06/07 23:51

学习Android的Http通信以来,接触了很多网络请求框架,尝试了他们各自的用法,但是没有做过系统的总结,以及对Http通信的理解,所以决定全面的整理一下Android实现Http通信过程,和各个网络请求框架的比较,加深学习印象。


Http请求简介

HyperText Transfer Protocol,超文本传输协议,是网络层的传输协议,Android和服务器通信通常采用HTTP通信和TCP通信,Android完全支持JDK本身的TCP,UDP网络通信,也支持JDK提供的URL,URLConnection,HttpURLConnection等网络通信API.

HttpURLConnection

首先要了解URL(uniform resource locator),他就像指向网络资源的指针,由协议名,主机,端口,和资源组成,通过函数openConnection()可以返回一个URLConnection对象。URLConnection表示应用程序和URL之间的通信连接,程序通过URLConnection的实例就可以实现向URL发送请求,读取URL应用的资源。

在Java中基础的Http请求访问步骤如下:

  1. 调用URL实例的openConnection()方法创建URLConnection对象
  2. 设置URLConnection参数和普通请求属性
  3. 如果只是发送GET请求,使用connect()方法建立和远程资源之间实际连接即可,如果发送POST请求,需要获取URLConnection对应的输出流来发送请求参数
  4. 连接建立,可以访问远程资源的头字段,也可以通过输入流来读取远程资源的数据

实现代码

public class HttpThread extends Thread {    private String url;    private WebView webView;    private Handler handler;    public HttpThread(String url,WebView webView,Handler handler){        this.url=url;        this.webView =webView;        this.handler =handler;    }    @Override    public void run() {        try {            URL murl = new URL(url);            try {               //建立连接                URLConnection coon =murl.openConnection();                coon.setConnectTimeout(5000);                coon.connect();                //读取资源                  InputStreamReader inputStreamReader =new InputStreamReader(coon.getInputStream());                BufferedReader bufferedReader =new BufferedReader(inputStreamReader);                String str;                final StringBuffer sb =new StringBuffer();                while((str=bufferedReader.readLine())!=null){                    sb.append(str);                }                //显示资源                handler.post(new Runnable() {                    @Override                    public void run() {                        webView.loadData(sb.toString(),"text/html;charset=utf-8",null);                    }                });            } catch (IOException e) {                e.printStackTrace();            }        } catch (MalformedURLException e) {            e.printStackTrace();        }    }}

而HttpConnection类是继承了URLConnection,也是用于向指定服务器发送GET,POST请求,也就是说他是URLConnection的进阶,他实现Http请求步骤如下:
1. 调用URL的openConnection()方法创建HttpURLConnection实例
2. 设置HttpURLConnection参数和普通请求属性
3. 使用setRequestMethond()方法确定发送哪种请求,如果发送POST请求,需要发送需要的请求参数。
4. 连接建立,可以访问远程资源的头字段,也可以通过输入流来读取远程资源的数据

实现代码:

public class HttpURLThread extends Thread {    private String url;    private WebView webView;    private Handler handler;    public HttpURLThread(String url,WebView webView,Handler handler){        this.url=url;        this.webView =webView;        this.handler =handler;    }    @Override    public void run() {        try {            URL mUrl =new URL(url);            try {                HttpURLConnection httpCoon =(HttpURLConnection) mUrl.openConnection();                httpCoon.setConnectTimeout(5000);                httpCoon.setRequestMethod("GET");                if(httpCoon.getResponseCode() == HttpURLConnection.HTTP_OK){                    InputStreamReader in =new InputStreamReader(httpCoon.getInputStream());                    BufferedReader br =new BufferedReader(in);                    final StringBuilder response = new StringBuilder();                    String line;                    while((line=br.readLine())!=null){                        response.append(line);                    }                    handler.post(new Runnable() {                        @Override                        public void run() {                            webView.loadData(response.toString(),"text/html;charset=utf-8",null);                        }                    });                }            } catch (IOException e) {                e.printStackTrace();            }        } catch (MalformedURLException e) {            e.printStackTrace();        }    }}

HttpClient

在一般情况下,如果只是需要向web站点的某个简单页面提交请求并获取服务器响应,HttpURLConnection就可以完成,但是对于大部分应用程序而言JDK本身提供的网络功能已远远不够,比如需要用户登录而且具有相应的权限才可以访问某个页面,还有涉及session和cookie的处理等。

为了解决这个问题,Android提供了Apache HttpClient,一个开源项目,功能更加完善,为客户端的Http编程提供高效、最新、功能丰富的工具包支持。

看名字就可以对HttpClient揣摩一二,他是一个简单的Http客户端而不是浏览器,可以用于发送HTTP请求,接受HTTP响应,但不会缓存服务器的响应,不能执行HTML界面中嵌入的JavaScript代码,也不会对页面内容进行任何解析,处理。换句话说:他很专注,他只会关注发送请求,响应请求,以及管理HTTP连接,其他多余的事情他是不会去做的。

通过HttpClient访问被保护资源时,程序需要使用HttpClient来登陆系统,只要程序使用了同一个HttpClient发送请求,HttpClient会自动维护与服务器之间的Session状态,也就是说程序第一次使用HttpClient登陆系统后,接下来使用HttpClient即可访问被保护的资源,这一点和浏览器实现访问被保护资源很像(也是维护与服务器之间的Session)。

如果我们要使用HttpClient的话,使用步骤如下:

  1. 创建一个DefaultHttpClient实例
  2. 如果要发起Get请求,需要创建一个HttpGet对象,并传入请求地址;如果要发起Post请求,需要创建一个HttpPost对象。并传入请求地址,通过setEntity函数设置请求参数
  3. 调用execute方法,传入HttpGet或者HttpPost实例,执行后返回HttpResponse对象,判断响应状态码
  4. 解析响应结果,通过调用getEntity函数获得一个HttpEntity对象,之后可以通过EntityUtils.toString方法将其转换为字符串。

以GET请求为例

private String get(String url){        HttpClient client=null;        HttpGet request=null;        try {            client=new DefaultHttpClient();            request=new HttpGet(url);            HttpResponse response=client.execute(request);            if(response.getStatusLine().getStatusCode()== HttpStatus.SC_OK){                String result=EntityUtils.toString(response.getEntity(),"UTF-8");                return result;            }        } catch (IOException e) {            e.printStackTrace();        }        return  null;    }

至此,让我们先来简单比较一下HttpUrlConnection和HttpClient,Android系统最开始使用的网络请求是HttpURLConnection,为了提高http访问的高效和稳定,又引入了HttpClient,但随着时间发展,加之HttpClient的维护成本高昂,android开发团队不愿意再维护HttpClient,而转投开始维护更为轻便的HttpURLConnection,因为HttpURLConnection更加的轻便,灵活,易于扩展。

在android3.0以后及4.0中都对HttpURLConnection进行了改善,添加了对于https的支持,4.0以后还添加了对缓存的支持。

目前的情况是Android6.0已经废弃了HttpClient。所以基于HttpClient的网络请求框架也是不建议再使用的。

AsyncHttpClient

正如之前提到的,AsyncHttpClient 就是基于HttpClient的网络请求架构,所以这个库现在不建议使用了。

我接触这个库并使用还是在大二的时候,由他的名字也可以看出他的特点,异步的HttpClient,所有请求独立在UI主线程之外,通过回调方法处理请求结果,采用Handler-Message机制传递信息。

总结AsyncHttpClient的特点:

  • 所以请求在子线程中完成,请求回调在调用该请求的线程中完成
  • 使用线程池
  • 使用RequestParams类封装请求参数
  • 支持文件上传
  • 持久化cookie到SharedPreferences,个人感觉这一点也是这个库的重要特点,可以很方便的完成一些模拟登录
  • 支持json
  • 支持HTTP Basic Auth

volley

既然在android2.2之后不建议使用Http Client,那么有没有一个库是android2.2及以下版本使用Http Client,而android2.3及以上版本使用HttpUrlConnection的呢,答案是肯定的,就是Volley,它是android开发团队在2013年Google I/O大会上推出了一个新的网络通信框架

volley的出现主要是为了提高网络通信的速度和简化网络通信的步骤。Volley可是说是把AsyncHttpClient和Universal-Image-Loader的优点集于了一身,既可以像AsyncHttpClient一样非常简单地进行HTTP通信,也可以像Universal-Image-Loader一样轻松加载网络上的图片。
它提供了如下的便利功能:

  • JSON,图像等的异步下载;
  • 网络请求的排序(scheduling)
  • 网络请求的优先级处理
  • 缓存
  • 多级别取消请求
  • 和Activity和生命周期的联动(Activity结束时同时取消所有网络请求)

它的设计目标就是非常适合去进行数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。

使用volley进行网络通信,主要步骤如下:

  1. 创建一个RequestQueue对象。

  2. 创建一个Request对象。

  3. 将Request对象添加到RequestQueue里面。

以GET请求为例:

RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);               String url ="http://www.baidu.com";               StringRequest stringRequest =new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {                   @Override                   public void onResponse(String response) {                       Log.d("TAG",response.toString());                   }               }, new Response.ErrorListener() {                   @Override                   public void onErrorResponse(VolleyError error) {                   }               });               requestQueue.add(stringRequest);

对于post请求,我们需要重载Request中的getParams()方法来添加对应参数(volley中没有直接设置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;    }};

加载图片和上面类似,只不过把StringRequest换成ImageRequest,他们都是继承自抽象类Request的具体实现类,由此我们也可以看出volley的可扩展性,在实际应用的时候,我们完全可以创建继承Request的自定义Rquest,你可以自由的在里面添加和修改任何的方法,方便你自己的使用。

此外,Volley提供了一个新的控件NetworkImageView来代替传统的ImageView,该控件的图片属性可以通过setImageUrl(url, imageLoader)来进行设置,而且这个控件在被从父控件detach的时候,会自动取消网络请求的,即完全不用我们担心相关网络请求的生命周期问题。

okHttp

okHttp是Java的HTTP+SPDY客户端开发包,支持Android(2.3以上),我学习的是okHttp3的使用,它相较2.X和1.X使用稍微有些变化,功能更加多,整体使用基本没有区别。

okHttp使用步骤:

  1. AS开发环境下添加依赖compile 'com.squareup.okhttp3:okhttp:3.6.0' okHttp内部依赖okio,因此还需要添加依赖compile 'com.squareup.okio:okio:1.11.0'
  2. 创建OkHttpClient
  3. 创建Request (builder模式创建)
  4. 让OkHttpClient创建request对应的call
  5. call将请求加入调度,请求结果由callBack处理

以异步get请求为例:

private void doAsyncGet() {        mOkHttpClient = new OkHttpClient();        Request.Builder builder =new Request.Builder();        builder.url("http://www.baidu.com")                .method("GET",null);        Request request =builder.build();        Call call =mOkHttpClient.newCall(request);        call.enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {            }            @Override            public void onResponse(Call call, Response response) throws IOException {                Log.d(TAG,response.body().string());            }        });    }

需要注意的点:

  • onResponse回调的参数是response,一般情况下,如果我们希望获得返回的字符串,可以通过response.body().string()获取,如果希望返回二进制数组,可以调用response.body().bytes(),如果想返回inputstream,可以调用response.body().byteStream()

  • 对于call,我们可以异步执行,也可以以阻塞的方式运行,如果希望异步,则调用call.enqueue();如果希望阻塞,则调用call.execute()

  • 如果请求方式为post,对应的参数应该在参数体中,通过FormBody.Builder()添加需要的键值对,然后构造RequestBody,在post(RequestBody)中直接传入即可

至于okHttp的文件上传下载,在此不做展开,记录于具体的okHttp学习中。

总结okHttp的特点:

  • OKHttp是Android版Http客户端。非常高效,支持SPDY、连接池、GZIP和 HTTP 缓存。
  • 默认情况下,OKHttp会自动处理常见的网络问题,像二次连接、SSL的握手问题。
  • 如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其他网络层请求。
  • 从Android4.4开始HttpURLConnection的底层实现采用的是okHttp.

Retrofit

retrofit是由square公司开发的REST安卓客户端请求库,对于Android开发者来说,无疑是很好的选择,Retrofit的底层是基于okHttp实现的,他的优点很多:

  • 性能最好,处理最快
  • 使用REST API时非常方便;
  • 传输层默认就使用OkHttp;
  • 支持NIO;
  • 拥有出色的API文档和社区支持
  • 速度上比volley更快;
  • 如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其他网络层请求。
  • 默认使用Gson

Retrofit不同于前几种网络请求框架,他在使用的时候,将请求地址转化成了接口,通过 注解 来指定访问方式,请求参数,请求头,返回值等信息,还可以结合okhttp实现请求相关操作,比如设置cookie,修改请求头信息,拦截信息等。

关于Retrofit的具体使用可以参考之前的文章: Retrofit初了解 在这里就不做赘述了。

0 0
原创粉丝点击