欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 网络中HttpURLConnection用法解析

程序员文章站 2022-03-23 19:36:56
前言 前一篇文章中,我们了解了http协议的必备知识,这一篇我们还是从基础入手,介绍一下java的httpurlconnection,它虽基础,但却很重要,许多网络框架都是基于它开发的,因此我们还是...

前言

前一篇文章中,我们了解了http协议的必备知识,这一篇我们还是从基础入手,介绍一下java的httpurlconnection,它虽基础,但却很重要,许多网络框架都是基于它开发的,因此我们还是要好好的学一下关于httpurlconnection的使用。

android 网络(八) retrofit解析
http协议相关知识如请求报头请求数据请求方法(post和get的区别)等有疑问的同学,建议先android 网络(一) http协议,了解基础知识后,再阅读本文

httpurlconnection简介

敲黑板!google建议我们使用httpurlconnection类发送http请求,它的重要性,不用我多说了吧。
httpurlconnection是urlconnection的子类,后者在google官方文档中的定义是这样的

the abstract class urlconnection is the superclass of all classes that represent a communications link between the application and a url. instances of this class can be used both to read from and to write to the resource referenced by the url.

简单说,urlconnection是一个抽象类,表示指向url制定资源的活动链接,其本身依赖于socket类实现网络连接。
而httpurlconnection从字面上就能猜到它是干什么的了。没错,这个类用来实现基于http url的请求、响应功能,每个httpurlconnection实例都可用于生成单个网络请求,支持get、post、put、delete等方式,最常用的也就是getpost,本文也将就这两种请求方式进行讲解。

android sdk对http的支持除了上面httpurlconnection,原本还有另外一个常用的接口,apache接口–httpclient,但是优于其api数量过多、扩展困难等缺点,google在android 6.0(api 23)中移除了httpclient,标志着google正式启用此功能。

基本流程

获取httpurlconnection实例:调用url.openconnection(),并进行转型。 设置请求报头:最重要的部分是uri,同时也包括元数据,内容类型,cookies等。 设置请求数据(post方式时需要此步):如果含有请求数据,那么实例需要调用setdooutput(true)。通过写入getoutputstream()返回的流来传输数据。 读取响应数据:包括响应报头,以及响应报文。响应报文通过getinputstream()返回的流中读取。 断开连接:disconnect()
当然,涉及到网络访问,我们需要在manifest文件中添加网络访问权限

get请求的使用方法

示例如下:

private void useget(string requesturl) {
        try {
            //接收响应报文
            textshow = new stringbuilder("this is 'get' " + "\n");
            //url对象
            url url = new url(requesturl);
            //获取httpurlconnection实例
            mconnection = (httpurlconnection) url.openconnection();
            //设置get请求方法
            mconnection.setrequestmethod(method_get);
            //建立连接
            mconnection.connect();
            //根据响应码判断连接是否成功
            if (mconnection.getresponsecode() == httpurlconnection.http_ok){
                //将响应流转换成字符串
                bufferedreader reader = new bufferedreader(new inputstreamreader(mconnection.getinputstream()));
                string line = "";
                while ((line = reader.readline())!=null){
                    textshow.append(line);
                }
            }
            //子线程更新ui的其中一种方式
            runonuithread(new runnable() {
                @override
                public void run() {
                    mtextview.settext(textshow);
                }
            });
        } catch (exception e) {
            e.printstacktrace();
        }
    }

注意事项:

httpurlconnection是同步的请求,必须放在子线程 对请求行、请求报头的设置必须放在connection.connect()前 connection.getinputstream()得到一个流对象,而不是数据;从这个流对象中只能读取一次数据,第二次读取时将会得到空数据 子线程不能直接更新ui,需要借助一些手段,如runonuithread()、handler、handerthread等

post请求的使用方法

示例如下:

private void usepostparams(string requesturl){
        try {
            url url = new url(requesturl);
            mconnection = (httpurlconnection) url.openconnection();
            //设置链接超时时间
            mconnection.setconnecttimeout(10000);
            //设置读取超时时间
            mconnection.setreadtimeout(15000);
            //设置请求方法
            mconnection.setrequestmethod(method_post);
            //添加header
            mconnection.setrequestproperty("connection","keep-alive");
            //接受输入流
            mconnection.setdoinput(true);

            //有请求数据时,必须开启此项!
            mconnection.setdooutput(true);
            //post不支持缓存
            mconnection.setusecaches(false);

            mconnection.connect();

            //传输'请求数据'
            string body = "username=whdalive&password=123456";
            bufferedwriter writer = new bufferedwriter(new outputstreamwriter(mconnection.getoutputstream(),"utf-8"));
            writer.write(body);
            writer.flush();
            writer.close();

            textshow = new stringbuilder("this is 'post with params' " + "\n");
            if (mconnection.getresponsecode() == httpurlconnection.http_ok){
                inputstream inputstream = mconnection.getinputstream();
                bufferedreader reader = new bufferedreader(new inputstreamreader(inputstream));
                string line = "";
                while ((line=reader.readline())!=null){
                    textshow.append(line);
                }
            }
            runonuithread(new runnable() {
                @override
                public void run() {
                    mtextview.settext(textshow);
                }
            });
        } catch (exception e) {
            e.printstacktrace();
        }
    }

注意事项:

post请求和get请求有很多相似,除了上面提到的get方法的注意事项以外,还需要注意连接之前额外加入的一些设置,如:

post方式不支持缓存,必须调用mconnection.setusecaches(false) 有请求数据时,必须调用mconnection.setdoinput(true)

post传输json数据:在请求头中设置参数类型是json格式,并传入json格式的字符串到body即可。

post上传文件:在请求头中设置参数类型是file类型,并将文件封装成一个流传入body即可。 post同时上传参数和文件:原理和上述无二,只不过由于没有直接同时上传参数和文件的api,需要我们手动完成数据的封装。 post方式传递参数/json/文件等数据的本质:从连接中得到一个输出流,通过输出流把相应数据(键值对参数/json/文件等)写到服务器

应用举例-下载图片

示例如下:

 private void downloadpic(string requesturl){
      try {
          //获取网络图片的url
          url url = new url(requesturl);
          //获取httpurlconnection实例
          mconnection = (httpurlconnection) url.openconnection();
          //设置post方式
          //下载图片这个场景中,post和get都可以
          mconnection.setrequestmethod(method_post);
          //接受输入流
          mconnection.setdoinput(true);

          mconnection.setdooutput(true);
          //post方式不支持缓存
          mconnection.setusecaches(false);
          //建立连接
          mconnection.connect();
          //获取响应流
          inputstream in = mconnection.getinputstream();
          //将响应流转换成bitmap
          final bitmap bitmap = bitmapfactory.decodestream(in);
          //子线程更新ui,显示图片
          runonuithread(new runnable() {
              @override
              public void run() {
                mimageview.setimagebitmap(bitmap);
              }
          });
      }catch (exception e){
          e.printstacktrace();
      }
    }

注意事项

下载图片和其他类型数据本质是一样的:
得到响应流,从流中读出数据,对不同类型数据采取不同处理方式 建议自己动手实践一下,体会各个应用场景下不同数据的处理方式。

总结

本文详细介绍了httpurlconnection的使用。 笔者水平有限,如有错漏,欢迎指正。 接下来我将持续推出android网络相关的一系列文章,包括httpurlconnection、volley、okhttp3、retrofit2的使用等。