CachedNetworkImage là widget Flutter để tải và lưu đệm hình ảnh từ mạng với hỗ trợ chỉ báo tiến trình, placeholder và xử lý lỗi. Theo trang gói chính thức, thư viện dựa trên flutter_cache_manager và cung cấp bộ nhớ đệm tự động trên đĩa với TTL có thể cấu hình. CachedNetworkImage là giải pháp tiêu chuẩn để tải hình ảnh trong các ứng dụng Flutter có bộ nhớ đệm.
Những điểm chính
CachedNetworkImage là widget Flutter từ gói cùng tên trên pub.dev cung cấp khả năng tải hình ảnh từ mạng với bộ nhớ đệm tự động. Nó là một lớp bao bọc xung quanh Image.network tiêu chuẩn, thêm bộ nhớ đệm tệp, chỉ báo tiến trình và xử lý lỗi tùy chỉnh.
Bên trong, CachedNetworkImage sử dụng flutter_cache_manager — trình quản lý bộ nhớ đệm với cơ sở dữ liệu SQLite để theo dõi tệp. Ở yêu cầu đầu tiên, hình ảnh được tải xuống từ mạng, lưu vào đĩa và ở các yêu cầu tiếp theo được phục vụ từ bộ nhớ đệm có tính đến TTL (mặc định 7 ngày). Bộ nhớ đệm trong bộ nhớ được quản lý bởi ImageCache tiêu chuẩn của Flutter.
Gói này có hơn 4.000 lượt thích trên pub.dev và được sử dụng trong hàng nghìn dự án Flutter. CachedNetworkImage hỗ trợ tất cả các nền tảng Flutter: Android, iOS, Web, macOS, Windows và Linux. Nhờ API thống nhất, các nhà phát triển có được khả năng tải hình ảnh đa nền tảng mà không cần mã dành riêng cho từng nền tảng.
Flutter sử dụng hệ thống bộ nhớ đệm hai cấp: ImageCache (bộ nhớ) và flutter_cache_manager (đĩa + SQLite). ImageCache là bộ nhớ đệm toàn cục của hình ảnh đã giải mã với giới hạn về số lượng (mặc định 1000) và kích thước (mặc định 100 MB). flutter_cache_manager quản lý các tệp trên đĩa và siêu dữ liệu của chúng.
Khi CachedNetworkImage nhận được yêu cầu hình ảnh, trước tiên nó kiểm tra ImageCache của Flutter — nếu hình ảnh đã được giải mã trong bộ nhớ, nó được hiển thị ngay lập tức. Khi bộ nhớ đệm không có, đĩa được kiểm tra qua flutter_cache_manager: một truy vấn SQLite kiểm tra xem tệp có tồn tại trong bộ nhớ đệm hay không và TTL của nó đã hết hạn chưa. Nếu tệp còn hiệu lực — nó được đọc từ đĩa, giải mã và hiển thị. Nếu tệp bị thiếu hoặc TTL đã hết hạn — một yêu cầu HTTP được thực hiện.
DefaultCacheManager cung cấp các phương thức emptyCache() (dọn dẹp hoàn toàn), cleanCache() (chỉ xóa mục đã hết hạn) và clearCacheWithAge() với ngày tùy chỉnh. ImageCache được dọn dẹp tự động khi áp lực bộ nhớ hoặc thủ công qua imageCache.clear().
CachedNetworkImage được xây dựng trên sự kết hợp các widget Flutter tiêu chuẩn. Triển khai nội bộ sử dụng ImageProvider để tải bất đồng bộ và StatefulWidget để quản lý vòng đời.
imageUrl — tham số bắt buộc, URL hình ảnh (String hoặc Uri). placeholder — widget hiển thị trong khi tải. errorWidget — widget khi lỗi tải. progressIndicatorBuilder — builder nhận ngữ cảnh, URL và DownloadProgress với các trường totalSize và downloadedSize.
CachedNetworkImageProvider — triển khai ImageProvider trả về CachedNetworkStreamImage, quản lý việc tải xuống và lưu đệm. Nhà cung cấp tích hợp với ImageCache của Flutter và hỗ trợ tất cả các khả năng ImageProvider tiêu chuẩn: chia tỷ lệ, căn giữa và lặp lại.
flutter_cache_manager là thư viện nền tảng cho bộ nhớ đệm của CachedNetworkImage. Nó cung cấp DefaultCacheManager với cơ sở dữ liệu SQLite đã được cấu hình, TTL và giới hạn tệp. Nếu cần, có thể tạo CacheManager tùy chỉnh với các tham số riêng.
| Tham số | Mô tả | Giá trị mặc định |
|---|---|---|
| maxAgeCacheObject | Thời gian lưu trữ tệp tối đa | 7 ngày |
| maxNrOfCacheObjects | Số lượng tệp tối đa | 200 |
| key | Định danh duy nhất của trình quản lý | “default” |
| repo | Loại lưu trữ siêu dữ liệu | CacheObjectRepository (SQLite) |
| fileService | HTTP client để tải xuống | HttpFileService |
CacheManager tùy chỉnh được tạo bằng cách kế thừa từ CacheManager với ghi đè phương thức. Điều này hữu ích khi cần lưu trữ hình ảnh trong thư mục riêng hoặc sử dụng HTTP client khác. Instance của trình quản lý sau đó được truyền vào tham số cacheManager của CachedNetworkImage.
Cơ sở dữ liệu SQLite của DefaultCacheManager nằm trong temporaryDirectory của ứng dụng tại đường dẫn `{key}/CacheObjects.db`. Nó chứa bảng cacheObjects với các trường: key (URL), relativePath, url, creationDate, eTag, httpHeaders. Khi dọn dẹp các mục đã hết hạn, truy vấn SQL với điều kiện trên maxAgeCacheObject được sử dụng.
CachedNetworkImage cung cấp hai cách tiếp cận tải chính: widget CachedNetworkImage và CachedNetworkImageProvider cho các tình huống tùy chỉnh.
CachedNetworkImage — cách tiếp cận chính. Chỉ cần truyền imageUrl và placeholder. Widget tự động hiển thị placeholder cho đến khi tải hoàn tất và thay thế nó bằng hình ảnh.
CachedNetworkImage(
imageUrl: "https://example.com/photo.jpg",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
width: 200,
height: 200,
fit: BoxFit.cover,
)
placeholder và errorWidget là các hàm builder nhận ngữ cảnh, URL và (đối với errorWidget) một đối tượng lỗi. Cách tiếp cận này cho phép hiển thị các placeholder khác nhau tùy theo URL hoặc loại lỗi.
progressIndicatorBuilder — tham số cho phép hiển thị tiến trình tải xuống dưới dạng phần trăm. DownloadProgress chứa totalSize (có thể là -1 nếu không xác định) và downloadedSize.
CachedNetworkImage(
imageUrl: "https://example.com/large.jpg",
progressIndicatorBuilder: (context, url, downloadProgress) {
return Center(
child: SizedBox(
width: 50,
height: 50,
child: Stack(
alignment: Alignment.center,
children: [
CircularProgressIndicator(
value: downloadProgress.progress,
),
Text(
"\(downloadProgress.downloadedSize ~/ 1024) KB",
),
],
),
),
};
},
imageBuilder: (context, imageProvider) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
};
},
)
imageBuilder — tham số tùy chọn cho phép tùy chỉnh hiển thị hình ảnh: thêm góc bo tròn, đổ bóng, trang trí. Ví dụ sử dụng DecorationImage với BorderRadius cho các góc bo tròn.
CachedNetworkImageProvider — nhà cung cấp cho Image hoặc DecorationImage mà không cần sử dụng widget CachedNetworkImage. Hữu ích khi làm việc với BoxDecoration, FadeInImage hoặc các widget Image tùy chỉnh.
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: CachedNetworkImageProvider(
"https://example.com/bg.jpg",
maxWidthBytes: 2048,
maxHeightBytes: 2048,
),
fit: BoxFit.cover,
),
),
)
Tham số imageBuilder trong CachedNetworkImage cho phép ghi đè widget Image tiêu chuẩn bằng triển khai tùy chỉnh. Thay vì hiển thị trực tiếp Image, bạn có thể sử dụng Container với trang trí, ClipRRect để cắt, hoặc Ink.image để tạo hiệu ứng gợn sóng. imageBuilder nhận ngữ cảnh và ImageProvider của hình ảnh đã sẵn sàng, cho phép kiểm soát hoàn toàn việc hiển thị.
Các tham số bổ sung: memCacheWidth và memCacheHeight giới hạn kích thước hình ảnh trong bộ nhớ đệm, giảm tải cho ImageCache của Flutter. cacheKey cho phép đặt khóa bộ nhớ đệm tùy chỉnh thay vì URL, hữu ích cho hình ảnh có mã thông báo ủy quyền trong URL (các tham số truy vấn thay đổi theo mỗi yêu cầu nhưng nội dung vẫn giữ nguyên).
Widget Image.network tiêu chuẩn tải hình ảnh mỗi khi widget được xây dựng lại mà không lưu vào đĩa. CachedNetworkImage thêm bộ nhớ đệm tệp, chỉ báo tiến trình và xử lý lỗi, nhưng thêm phụ thuộc vào flutter_cache_manager và SQLite.
| Tiêu chí | Image.network | CachedNetworkImage |
|---|---|---|
| Bộ nhớ đệm trên đĩa | Không (chỉ bộ nhớ đệm của Flutter) | Có (SQLite + tệp) |
| Tiến trình | Không | progressIndicatorBuilder |
| Widget lỗi | Chỉ placeholder đỏ trong debug | errorWidget tùy chỉnh |
| TTL bộ nhớ đệm | Không áp dụng | Có thể cấu hình (mặc định 7 ngày) |
| Phụ thuộc | Không có (tích hợp trong Flutter) | cached_network_image + flutter_cache_manager + sqflite |
| Truy cập ngoại tuyến | Không | Có (với tệp đã tải trước đó) |
| Kích thước build | 0 KB bổ sung | ~300 KB bổ sung |
Đối với các dự án mà khả năng ngoại tuyến và tiết kiệm băng thông là quan trọng, CachedNetworkImage là lựa chọn rõ ràng. Đối với các màn hình đơn giản một lần (ví dụ: onboarding hoặc splash), Image.network không yêu cầu phụ thuộc bổ sung.
CachedNetworkImage được thêm như một phụ thuộc pub.dev tiêu chuẩn. Sau khi cài đặt, widget đã sẵn sàng để sử dụng. flutter_cache_manager được bao gồm như một phụ thuộc truyền dẫn.
// pubspec.yaml
dependencies:
flutter:
sdk: flutter
cached_network_image: ^3.4.1
Theo mặc định, DefaultCacheManager được sử dụng với các thiết lập: TTL = 7 ngày, tối đa 200 tệp. Để thay đổi các tham số toàn cục, một instance CacheManager tùy chỉnh được tạo với Config, nơi maxAgeCacheObject, maxNrOfCacheObjects và repo được ghi đè.
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
final customCacheManager = CacheManager(
Config(
"custom_images",
stalePeriod: Duration(days: 14),
maxNrOfCacheObjects: 500,
repo: JsonCacheInfoRepository(
databaseName: "custom_images_cache.db",
),
),
);
// Sử dụng trình quản lý tùy chỉnh:
CachedNetworkImage(
cacheManager: customCacheManager,
imageUrl: url,
// ...
)
maxWidthBytes và maxHeightBytes — các tham số tùy chọn để giới hạn kích thước tệp trong bộ nhớ đệm. Điều này hữu ích để tiết kiệm dung lượng đĩa khi hình ảnh gốc lớn hơn kích thước màn hình yêu cầu.
Câu hỏi thường gặp
CachedNetworkImage là widget Flutter để tải hình ảnh từ mạng với bộ nhớ đệm tự động trên đĩa. Nó cần thiết để tiết kiệm băng thông, hoạt động ở chế độ ngoại tuyến và hiển thị tiến trình tải xuống, điều mà Image.network tiêu chuẩn không cung cấp.
Thêm cached_network_image: ^3.4.1 vào phần dependencies của pubspec.yaml và chạy flutter pub get. Sau đó import gói trong tệp của bạn: import 'package:cached_network_image/cached_network_image.dart'.
Tạo CacheManager tùy chỉnh với Config nơi tham số stalePeriod được chỉ định là Duration. Truyền trình quản lý đã tạo vào tham số cacheManager của widget CachedNetworkImage. Theo mặc định, các tệp được lưu trữ trong 7 ngày.
Gọi DefaultCacheManager().emptyCache() để dọn dẹp hoàn toàn tất cả các tệp. Để chỉ xóa các tệp đã hết hạn, sử dụng cleanCache(). Trình quản lý tùy chỉnh được xóa bằng cách gọi emptyCache trên instance của nó.
Có, CachedNetworkImage hỗ trợ Android, iOS, Web, macOS, Windows và Linux. API thống nhất đảm bảo hành vi nhất quán trên tất cả các nền tảng, và bộ nhớ đệm hoạt động thông qua flutter_cache_manager, được điều chỉnh cho từng hệ điều hành.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm