圖片框架使用問題之三: Fresco框架加載本地圖片失敗(文件名包含特殊字符)


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, 加載本地文件之特殊文件名

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,455評論 25 708
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,973評論 19 139
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,537評論 0 17
  • Fresco簡單的使用—SimpleDraweeView 百學須先立志—學前須知: 在我們平時加載圖片(不管是下載...
    天天大保建閱讀 3,470評論 0 8
  • 在受到了太多的誤解之后,和陰郁宮廷范兒的哥特音樂比起來,朋克雖然是搖滾樂眾多流派之母,但他可不是娘娘腔。 朋克音樂...
    maofay閱讀 386評論 0 1