在 App 中會經常遇到需要從後臺拉取圖片的場景,這一方面會給服務器帶來網絡帶寬消耗,另一方面加載圖片的等待過程也會影響用戶體驗。因此,往往會在 App 端對圖片做緩存機制,以避免同一張圖片反覆發起請求。在 Flutter 中,cached_network_image 即提供了緩存網絡圖片功能,同時還提供了豐富的加載過程指示。
上一篇我們使用了列表,其中列表中有從網絡下載圖片。直接使用 Flutter 自帶的 Image.network 下載圖片一是無法緩存,二是體驗不夠好。熟悉 iOS 的肯定知道 SDWebImage,即 Objective-C 上用得最廣泛的圖片緩存開源組件。與 SDWebImage 類似,Flutter 的 cached_network_image
插件也實現了這樣的功能。cached_network_image
使用十分簡單,首先在 pubspec.yaml 中添加依賴:
dependencies:
flutter:
sdk: flutter
# ...其他依賴
cached_network_image: ^3.0.0
之後在需要使用 cached_network_image
的地方引入源碼:
import 'package:cached_network_image/cached_network_image.dart';
最後在需要加載網絡圖片的地方使用cached_network_image
替代原有的圖片加載方式(如 Image.network):
CachedNetworkImage(imageUrl: "http://via.placeholder.com/350x150"),
以上是 cached_network_image
最簡單的用法,當然爲了用戶體驗更好,推薦是使用佔位圖或加載指示器的方式提示用戶圖片正在加載。
使用佔位圖
CachedNetworkImage
提供了佔位圖和加載失敗後的錯誤指示的方法用於靜態指示。我們分別準備 image-default.png 和 image-failed.png 文件表示默認佔位圖和加載失敗後的佔位圖,然後用 CachedNetworkImage
構造方法的 placeholder
和 errorWidget
來使用佔位圖,如下所示:
Widget _imageWrapper(String imageUrl) {
return SizedBox(
width: 150,
height: ITEM_HEIGHT,
child: CachedNetworkImage(
imageUrl: imageUrl,
placeholder: (context, url) => Image.asset('images/image-default.png'),
errorWidget: (context, url, error) =>
Image.asset('images/image-failed.png'),
),
);
}
}
使用進度加載指示
也可以使用進度加載指示器來指示加載進度,加載進度指示支持原型進度和線型進度。這種對於大圖預覽時會更爲常用,代碼如下所示,其中LinearProgressIndicator
是線型指示器,CircularProgressIndicator
是圓形指示器:
Widget _imageWrapper(String imageUrl) {
return SizedBox(
width: 150,
height: ITEM_HEIGHT,
child: CachedNetworkImage(
imageUrl: imageUrl,
progressIndicatorBuilder: (context, url, downloadProgress) =>
LinearProgressIndicator(value: downloadProgress.progress),
errorWidget: (context, url, error) =>
Image.asset('images/image-failed.png'),
),
);
}
效果
效果如下圖所示,下拉刷新後,可以先看到佔位圖,然後逐漸過渡到加載成功的圖片。如果修改鏈接爲一個非法鏈接或資源不存在的鏈接,則會顯示圖片加載失敗的佔位圖。這種體驗相比空白沒有任何指示的 Image.network好很多。