Android 网络中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等方式,最常用的也就是get和post,本文也将就这两种请求方式进行讲解。
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(); } }
注意事项:
下载图片和其他类型数据本质是一样的:得到响应流,从流中读出数据,对不同类型数据采取不同处理方式 建议自己动手实践一下,体会各个应用场景下不同数据的处理方式。