日常开发——Android网络请求openConnection()源码分析

本文分析了Android中进行HTTP GET请求时,为何会出现两次接口调用的问题。通过研究`openConnection()`、`getInputStream()`和`getOutputStream()`方法的源码,揭示了在使用URL对象进行网络请求时,隐式连接和数据获取的过程。`openConnection()`初始化连接并提供响应信息,而`getInputStream()`和`getOutputStream()`会导致实际的网络交互。
摘要由CSDN通过智能技术生成

问题

        最近项目需要一个下载的功能,所以在安卓端实现了一个普遍的下载功能模块。但Protal admin端发来信息说,怎么安卓端cal了l两次下载接口,当时以为是代码写错了,改了几次之后发现问题还在。经过网上搜索以及源码分析之后,才知道这是安卓或者说Java封装API的原因。

安卓端,使用Thread实现一个http get请求普遍方法:

<pre name="code" class="java">@Override
    public void run(){
        HttpURLConnection connection = null;
        BufferedInputStream bis  = null ;
        RandomAccessFile accessFile = null ;
        try{
            URL url = new URL(url_str);
            connection = (HttpURLConnection)url.openConnection();
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);
            fileSize = connection.getContentLength();
            //package name
            String con_dis = connection.getHeaderField("Content-Disposition");
            fileName = con_dis.substring(con_dis.indexOf('"')+1,con_dis.lastIndexOf('"'));
            Log.e("Name", fileName);
            //以 路径+文件名 创建文件
            File saveFile = new File(path+"/"+fileName);

            //操作文件,设置长度
            accessFile = new RandomAccessFile(saveFile,"rwd");
            accessFile.setLength(fileSize);

            //buffer空间

            byte[] buffer = new byte[BUFF_SIZE];

            bis = new BufferedInputStream(connection.getInputStream(),BUFF_SIZE);
            int len ;

            //写入buffer空间
            while((len = bis.read(buffer,0,BUFF_SIZE))!= -1){
                accessFile.write(buffer,0,len);    //写入文件
                downSize = downSize + len;
                downPercent = (downSize*100)/fileSize;
            }

            /**
             * 自动安装
             */
            Message msg = new Message();
            msg.what = 1 ;        //下载完成
            Bundle bundle = new Bundle();
            bundle.putString("filePath", saveFile.getAbsolutePath());
            msg.setData(bundle);
            handler.sendMessage(msg);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //close
            if(connection!=null){
                connection.disconnect();
            }
            try{
                if(bis!=null){
                    bis.close();
                }
                if(accessFile!=null){
                    accessFile.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }


 通过Protal admin端日志发现上述代码会call两次URL。先说结论: 

1.第一次call发生在url.openConnection();

2.第二次call发生在connection.getInputStream();

openConnection()

        如果创建了一个含有正确url的URL对象,并使用该对象的openConnection()方法时,该方法会先尝试进行请求以返回正确的URLConnection对象,请求不成功或协议不匹配则抛出异常。这也解释了为什么在执行完openConnection()之后,可以通过connection.getContentLength()、connection.getHeaderField()等方法获得关于这次请求的响应信息,然后通过这些信息来提前为正式的请求作一些准备(判断响应内容、创建文件、设置文件大小等)。

该方法将返回一个关于这次请求的HttpURLconnection对象,但在我想避免call两接口而想自己创建一个HttpURLConnection对象时,Gradle给我一个这样的回应:

connection = new HttpURLConnection() {
            @Override
            public void disconnect() {
                
            }

            @Override
            public boolean usingProxy() {
                return false;
            }

            @Override
            public void connect() throws IOException {

            }
        };
原来HttpURLCoonection是一个抽象的类,那么URL.openConnection()返回的是什么?想要解答疑问,还是要看回源码。

/**
 * Returns a new connection to the resource referred to by this URL.
 *
 * @throws
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值