Xutils3中的一些坑

      Xutil框架相信很多Android开发程序员都不陌生,Xutil集注解、网络、图片加载、数据库操作与一身的Android端框架,更新的Xutil3更简单的方便,在这里不针对Xutil的中心内容进行讲解,主要讲在使用Xutil中发现的问题。

一、Xutil中0B文件无法下载问题

      由于公司需要,对于文件下载、上传等需要对0B文件也做到兼容,但是后期测试发现Xutil3在下载0B文件后直接抛出了异常,具体的抛错地方如下。

Xutils3中的一些坑_第1张图片

Xutils3中的一些坑_第2张图片

     如果文件下载正常的话,我们下载一个文件的执行顺序如下(正常情况下):onWaiting-->onStarted-->onLoading-->onSuccess-->onFinished。正常的情况下是这样的,但是在下载0B文件时,意想不到的是执行完onStarted后,直接进入了onError方法,错误如下,竟然提示没有Cache file not found???

Xutils3中的一些坑_第3张图片

    对于0B文件下载的出错的处理,这里我偷了个懒,没有深入研究为什么抛出这个异常,而是在它回调到onError时,再进行进一步的判断,使用最基础的HttpURLConnection的方法上传,暂时处理一下这个问题(待深入-_-),具体代码如下。

 /**
     * 从网络Url中下载文件
     *
     * @param urlStr
     * @param savePath
     * @throws IOException
     */
    private void downLoadFromUrl(String urlStr, String savePath) {
       new Thread(){
           @Override
           public void run() {
               super.run();
               FileOutputStream fos = null;
               InputStream inputStream = null;
               try {
                   URL url = new URL(urlStr);
                   HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                   //设置超时间为3秒
                   conn.setConnectTimeout(3 * 1000);
                   //防止屏蔽程序抓取而返回403错误
                   conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

                   //得到输入流
                   inputStream = conn.getInputStream();
                   //获取自己数组
                   byte[] getData = readInputStream(inputStream);

                   //文件保存位置
                   File saveDir = new File(savePath);
                   if (!saveDir.getParentFile().exists()) {
                       saveDir.getParentFile().mkdir();
                   }
                   File file = new File(savePath);
                   fos = new FileOutputStream(file);
                   fos.write(getData);
                   //TODO: 这里实现你上传成功需要处理的逻辑
                   LogUtil.i("info:" + url + " download success");
               }catch (IOException ex){
                   ex.printStackTrace();
                   LogUtil.e(ex.getMessage());
                   //TODO:这里是一个简单错误日志异常上报 
                   new LogApi().uploadLog("downLoadFromUrl"
                           , DownloadCallback.class.getSimpleName()
                           , "try catch;" + ex.toString()
                                   + "ex.message:" + ex.getMessage() + ";"
                                   + "downloadInfo:" + downloadInfo.toString() + ";"
                           , 1);
                   //TODO: 这里实现你上传失败需要处理的逻辑
               }finally {
                   try {
                       if (fos != null) {
                           fos.close();
                       }
                       if (inputStream != null) {
                           inputStream.close();
                       }
                   }catch (IOException ex){
                       ex.printStackTrace();
                       LogUtil.e(ex.getMessage());
                       new LogApi().uploadLog("downLoadFromUrl"
                               , DownloadCallback.class.getSimpleName()
                               , "try catch finish;" + ex.toString()
                                       + "ex.message:" + ex.getMessage() + ";"
                                       + "downloadInfo:" + downloadInfo.toString() + ";"
                               , 1);
                        //TODO: 这里实现你上传失败需要处理的逻辑
                   }
               }
           }
       }.start();
    }

/**
     * 从输入流中获取字节数组
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

二、Xutil3中0B无法上传

    上一个问题,发现0B文件无法下载,测试上传时???,竟然直接出现红点,说上传错误,经过作者不懈努力的查找,终于发现了问题所在。原来Xutil3在添加上传文件的Body时使用到的MultipartBody中,初始化其中的CounterOutputStream时,调用其中的方法addStream,具体如下。>0????,猜到同仁们知道怎么改了吧,改成>=0,就可以上传了。修改的具体代码在MultipartBody-->CounterOutputStream-->addStream

public void addStream(InputStream inputStream) {
            if (total.get() == -1L) return;
            long length = InputStreamBody.getInputStreamLength(inputStream);

            //没错,就是这里>0?????????
            if (length > 0) {
                total.addAndGet(length);
            } else {
                total.set(-1L);
            }
        }

三、Xutils3下载、上传大于2G文件异常 

    此问题,具体表现,如下在下载2G文件时,它的onLoading竟然不调用。。。但是它一直在使用你的网络,如果你重新暂停以后再开始他又会调用了,但是进度会出现问题,一直百分之百。。。这个问题引发的原因,作者找了下,2G这个间隔是不是有点熟悉?没错,就是int类型的最大的取值范围,在框架内的具体体现,看官们请看下面具体代码。

    (1)FileLoader-->load(UriRequest)

Xutils3中的一些坑_第4张图片

     (2)HttpRequest 

Xutils3中的一些坑_第5张图片

    (3)URLConnection 

Xutils3中的一些坑_第6张图片

     (4)FileLoader-->load(UriRequest)

Xutils3中的一些坑_第7张图片

    (5)HttpTask 

 Xutils3中的一些坑_第8张图片

     上面几张图循序渐进,图一是针对于contentLength初始化,进入到图二、图三是具体调用的方法,看到图三,发现没有2G以上这里默认,返回的是-1,但是图四是整体控制onLoading的方法,>-1才执行(忘记具体代码,但是-1是绝对不会继续执行的)???,修改方案看官们也懂了吧?>=-1,让它继续执行下去;这里解决了第一次不会执行onLoading的方法,但是之后又有回调了,这是为什么呢?原来使我们设置了断点续传,会读取本地下载的长度,这个时候current的长度不为0,所以会执行onLoading的方法,但是由于那个长度溢出了,最后下载的时候onLoading中的total和current是一直相等的,这个时候如果你需要设置进度的话,你最好使用后台返回的文件大小进行设置,要不然会导致进度出现问题(如果还想改更底层,就只能对URLConnection了,由于系统已经完善,不能更改太多,暂时如此处理),如果修改了问题三的bug,这个时候你要注意total在第一次返回的时候会是0,如果有使用到就对他进行大于0的判断。

  public int getContentLength() {
        long l = getContentLengthLong();
        if (l > Integer.MAX_VALUE)
            return -1;
        return (int) l;
    }

    需要修改的代码HttpTask-->updateProgress。

Xutils3中的一些坑_第9张图片

Xutils3中的一些坑_第10张图片

四、Xutils3重定向使用问题

      这不能说是bug,只能说是使用问题,关于设置重定向问题,默认提示Xutil3是自动支持重定向的,过于相信没管它,但是测试后发现它不会自动重定向,怎么做呢?下面这样做就好。这里我是在自定义的请求中设置的,如果你只是一个实例,直接调用内部的setRedirectHandler方法就好,这里Location是需要重定向的地址。

/**
 * 自定义网络请求Header,携带及保存cookie
 * Created by yzy on 2018/4/8 10:15
 */

public class NetParams extends RequestParams {
    public NetParams(String uri) {
        super(uri);
        setRedirectHandler(uriRequest -> {

            RequestParams requestParams = uriRequest.getParams();
            String location = uriRequest.getResponseHeader("Location"); //协定的重定向地址
            if(!StringUtils.isEmptyOrNull(location)){
                requestParams.setUri(location); //重新设置url地址
            }
            return requestParams;
        });  //重定向

        setMaxRetryCount(5);  //重定向次数
    }
}

 

你可能感兴趣的:(Android)