美文网首页
图片框架使用问题之三: Fresco框架加载本地图片失败(文件名

图片框架使用问题之三: Fresco框架加载本地图片失败(文件名

作者: 元亨利贞o | 来源:发表于2016-12-07 16:10 被阅读1095次

    20150330130402_0.gif

    一. 问题

    使用的Fresco版本为: 0.14.1

    最近QA提了一个bug, 说项目中的一个图片选择页面的一张图片加载失败 (只有那一张图片失败, 其他的OK !). 瞬间蒙逼了......

    经过各种调试, 发现那张图片的名称非常诡异, 是这样的EOX}6W$Q~5U$5O3U%~R94]P.jpg. 我怀疑这张图片的命名有问题, 于是把名称改成a.jpg, 发现加载成功了!! 我加载图片的代码如下:

    SimpleDraweeView draweeView;
    //本地图片文件的路径, 如: `/storage/emulated/0/DCIM/Camera/EOX}6W$Q~5U$5O3U%~R94]P - 复制 (4).jpg`
    String filepath; 
    
    //省略无关代码 ......
    
    Uri uri = Uri.parse("file://" + filepath); //Uri.fromFile(new File(filepath));
    ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
            .setResizeOptions(new ResizeOptions(draweeView.getWidth(), draweeView.getHeight()))
            .build();
    
    DraweeController controller = Fresco.newDraweeControllerBuilder()
            .setOldController(targetView.getController())
            .setImageRequest(request)
            .setCallerContext(uri)
            .build();
    
    draweeView.setController(controller);
    

    URI中的特殊字符必须要经过转义, 否则会出问题. 更多讨论, 请看此issue

    Uri.parse()方法的定义如下:

    /**
     * Creates a Uri which parses the given encoded URI string.
     *
     * @param uriString an RFC 2396-compliant, encoded URI
     * @throws NullPointerException if uriString is null
     * @return Uri for this given uri string
     */
    public static Uri parse(String uriString) {
        return new StringUri(uriString);
    }
    

    从方法注释中可以看到, 此方法接收的参数是经过编码的uri字符串. 直接把文件的路径拼接一下传进去当然是不行的. 那么对文件路径拼接成的uri字符串进行编码, 然后传递给此方法不就可以了?! 然并卵!! 修改代码, 运行APP后发现所有图片都加载不出来了!! 上面的issue中有说到, 文件路径拼接成的uri字符串, 就算编码过再传给Uri.parse方法也是不行的 !!

    issue中的说明如下(后面一个方法名说错啦, 是Uri.fromFile(File file), 而不是Uri.parseFromFile()):

    F01BB8B9-E80B-41A5-A3AF-9BA8243C30ED.png

    二. 解决方案

    对于获取本地文件的uri对象, android.net.Uri类提供了一个静态方法: fromFile(File file). 其定义如下:

    /**
     * Creates a Uri from a file. The URI has the form
     * "file://<absolute path>". Encodes path characters with the exception of
     * '/'.
     *
     * <p>Example: "file:///tmp/android.txt"
     *
     * @throws NullPointerException if file is null
     * @return a Uri for the given file
     */
    public static Uri fromFile(File file) {
        if (file == null) {
            throw new NullPointerException("file");
        }
    
        PathPart path = PathPart.fromDecoded(file.getAbsolutePath());
        return new HierarchicalUri(
                "file", Part.EMPTY, path, Part.NULL, Part.NULL);
    }
    

    此方法接受一个文件对象, 然后返回此文件的Uri对象.
    对于获取文件的Uri对象, 推荐使用此方法 !

    最终解决方案: 使用android.net.Uri.fromFile(File file)方法获取本地文件的Uri对象.

    代码如下:

    Uri uri = Uri.fromFile(new File(filepath));
    

    .
    .
    .


    更多图片框架使用问题可以参考:
    图片框架使用问题之一: UIL导致的OOM
    图片框架使用问题之二: Fresco框架导致的OOM (com.facebook.imagepipeline.memory.BitmapPool.alloc(BitmapPool.java:4055))

    References:
    Fresco官方中文文档
    Fresco: issue#1088, 加载本地文件之特殊文件名

    相关文章

      网友评论

          本文标题:图片框架使用问题之三: Fresco框架加载本地图片失败(文件名

          本文链接:https://www.haomeiwen.com/subject/haudmttx.html