CachedNetworkImage هو Widget خاص بـ Flutter لتحميل الصور من الشبكة وتخزينها مؤقتاً مع دعم مؤشرات التقدم والـ placeholders ومعالجة الأخطاء. وفقاً للصفحة الرسمية للحزمة، تعتمد المكتبة على flutter_cache_manager وتوفر تخزيناً مؤقتاً تلقائياً على القرص مع TTL قابل للتكوين. CachedNetworkImage هو الحل المعياري لتحميل الصور في تطبيقات Flutter مع التخزين المؤقت.
النقاط الرئيسية
CachedNetworkImage هو Widget خاص بـ Flutter من الحزمة التي تحمل الاسم نفسه على pub.dev، ويوفر تحميل الصور من الشبكة مع تخزين مؤقت تلقائي. وهو غلاف حول Image.network القياسي، يضيف التخزين المؤقت للملفات ومؤشرات التقدم ومعالجة مخصصة للأخطاء.
داخلياً، يستخدم CachedNetworkImage flutter_cache_manager — مدير ذاكرة مؤقتة مع قاعدة بيانات SQLite لتتبع الملفات. في الطلب الأول، يتم تحميل الصورة من الشبكة وحفظها على القرص، وفي الطلبات اللاحقة يتم تقديمها من الذاكرة المؤقتة مع مراعاة TTL (افتراضياً 7 أيام). إدارة التخزين المؤقت في الذاكرة تتم عبر ImageCache القياسي لـ Flutter.
تتمتع الحزمة بأكثر من 4,000 إعجاب على pub.dev وتُستخدم في آلاف مشاريع Flutter. يدعم CachedNetworkImage جميع منصات Flutter: Android و iOS و Web و macOS و Windows و Linux. بفضل API موحد، يحصل المطورون على تحميل صور عبر المنصات دون كود خاص بمنصة معينة.
يستخدم Flutter نظام تخزين مؤقت ثنائي المستوى: ImageCache (ذاكرة) و flutter_cache_manager (قرص + SQLite). ImageCache هو ذاكرة مؤقتة عالمية للصور المفكوكة بحدود من حيث العدد (افتراضياً 1000) والحجم (افتراضياً 100 ميجابايت). يدير flutter_cache_manager الملفات على القرص وبياناتها الوصفية.
عندما يتلقى CachedNetworkImage طلب صورة، يتحقق أولاً من ImageCache الخاص بـ Flutter — إذا كانت الصورة قد فُكّت بالفعل في الذاكرة، يتم عرضها فوراً. في حالة عدم وجودها في الذاكرة المؤقتة، يتم التحقق من القرص عبر flutter_cache_manager: يقوم استعلام SQLite بالتحقق من وجود الملف في الذاكرة المؤقتة وما إذا كان TTL قد انتهى. إذا كان الملف محدثاً — يُقرأ من القرص ويُفك ويعرض. إذا كان الملف مفقوداً أو انتهى TTL — يتم إجراء طلب HTTP.
يوفر DefaultCacheManager طرق emptyCache() (تنظيف كامل)، cleanCache() (إزالة المنتهية فقط) و clearCacheWithAge() بتاريخ مخصص. يتم تنظيف ImageCache تلقائياً عند ضغط الذاكرة أو يدوياً عبر imageCache.clear().
تم بناء CachedNetworkImage على تركيب Widgets Flutter القياسية. يستخدم التنفيذ الداخلي ImageProvider للتحميل غير المتزامن و StatefulWidget لإدارة دورة الحياة.
imageUrl — معامل إلزامي، رابط الصورة (String أو Uri). placeholder — Widget يظهر أثناء التحميل. errorWidget — Widget عند خطأ التحميل. progressIndicatorBuilder — Builder يستقبل السياق والرابط و DownloadProgress مع حقلي totalSize و downloadedSize.
CachedNetworkImageProvider — تطبيق ImageProvider يعيد CachedNetworkStreamImage الذي يدير التحميل والتخزين المؤقت. يتكامل المزود مع ImageCache الخاص بـ Flutter ويدعم جميع إمكانيات ImageProvider القياسية: القياس والتمركز والتكرار.
flutter_cache_manager هي المكتبة الأساسية للتخزين المؤقت في CachedNetworkImage. توفر DefaultCacheManager مع قاعدة بيانات SQLite مهيأة و TTL وحداً للملفات. عند الحاجة، يمكن إنشاء CacheManager مخصص بمعاملات فريدة.
| المعامل | الوصف | القيمة الافتراضية |
|---|---|---|
| maxAgeCacheObject | أقصى مدة تخزين للملف | 7 أيام |
| maxNrOfCacheObjects | أقصى عدد من الملفات | 200 |
| key | معرف فريد للمدير | «default» |
| repo | نوع تخزين البيانات الوصفية | CacheObjectRepository (SQLite) |
| fileService | عميل HTTP للتحميل | HttpFileService |
يتم إنشاء CacheManager مخصص عن طريق الوراثة من CacheManager مع تجاوز الطرق. هذا مفيد عندما تحتاج الصور إلى التخزين في دليل منفصل أو استخدام عميل HTTP مختلف. ثم يتم تمرير نسخة المدير إلى معامل cacheManager الخاص بـ CachedNetworkImage.
توجد قاعدة بيانات SQLite الخاصة بـ DefaultCacheManager في temporaryDirectory الخاص بالتطبيق في المسار `{key}/CacheObjects.db`. تحتوي على جدول cacheObjects مع الحقول: key (URL)، relativePath، url، creationDate، eTag، httpHeaders. عند تنظيف الإدخالات المنتهية، يتم استخدام استعلام SQL بشرط على maxAgeCacheObject.
يوفر CachedNetworkImage طريقتين رئيسيتين للتحميل: Widget CachedNetworkImage و CachedNetworkImageProvider للسيناريوهات المخصصة.
CachedNetworkImage — الطريقة الرئيسية. يكفي تمرير imageUrl و placeholder. يعرض الـ Widget تلقائياً الـ placeholder حتى اكتمال التحميل ثم يستبدله بالصورة.
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 و errorWidget هما دالتي builder تستقبلان السياق والرابط و (لـ errorWidget) كائن الخطأ. يتيح هذا النهج عرض قوالب بديلة مختلفة حسب الرابط أو نوع الخطأ.
progressIndicatorBuilder — معامل يسمح بعرض تقدم التحميل كنسبة مئوية. يحتوي DownloadProgress على totalSize (قد يكون -1 إذا كان الحجم غير معروف) و 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 — معامل اختياري يسمح بتخصيص عرض الصورة: إضافة زوايا دائرية وظلال وزخارف. يستخدم المثال DecorationImage مع BorderRadius للزوايا الدائرية.
CachedNetworkImageProvider — مزود لـ Image أو DecorationImage دون استخدام Widget CachedNetworkImage. مفيد عند العمل مع BoxDecoration أو FadeInImage أو Widgets صور مخصصة.
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: CachedNetworkImageProvider(
"https://example.com/bg.jpg",
maxWidthBytes: 2048,
maxHeightBytes: 2048,
),
fit: BoxFit.cover,
),
),
)
يسمح المعامل imageBuilder في CachedNetworkImage بتجاوز Widget Image القياسي بتطبيق مخصص. بدلاً من عرض Image مباشرة، يمكنك استخدام Container مع زخرفة أو ClipRRect للقص أو Ink.image لتأثيرات التموج. يستقبل imageBuilder السياق و ImageProvider للصورة الجاهزة، مما يمنح تحكماً كاملاً في العرض.
معاملات إضافية: memCacheWidth و memCacheHeight يحددان حجم الصورة المخزنة مؤقتاً في RAM، مما يقلل الحمل على ImageCache الخاص بـ Flutter. cacheKey يسمح بتعيين مفتاح ذاكرة مؤقتة مخصص بدلاً من الرابط، وهو مفيد للصور ذات رموز التفويض في الرابط (تتغير معاملات الاستعلام مع كل طلب لكن المحتوى يبقى نفسه).
Widget Image.network القياسي يقوم بتحميل الصورة في كل إعادة بناء للـ Widget دون حفظ على القرص. يضيف CachedNetworkImage التخزين المؤقت للملفات ومؤشرات التقدم ومعالجة الأخطاء، لكنه يضيف تبعية لـ flutter_cache_manager و SQLite.
| المعيار | Image.network | CachedNetworkImage |
|---|---|---|
| ذاكرة تخزين مؤقتة على القرص | لا (ذاكرة Flutter المؤقتة فقط) | نعم (SQLite + ملفات) |
| مؤشر التقدم | لا | progressIndicatorBuilder |
| Widget الخطأ | Placeholder أحمر فقط في وضع التصحيح | errorWidget مخصص |
| TTL الذاكرة المؤقتة | غير قابل للتطبيق | قابل للتكوين (7 أيام افتراضياً) |
| التبعيات | لا شيء (مدمج في Flutter) | cached_network_image + flutter_cache_manager + sqflite |
| الوصول دون اتصال | لا | نعم (مع الملفات المحملة مسبقاً) |
| حجم البناء | 0 كيلوبايت إضافية | ~300 كيلوبايت إضافية |
للمشاريع التي تكون فيها القدرة على العمل دون اتصال وتوفير النطاق الترددي مهمة، فإن CachedNetworkImage هو الخيار الواضح. للشاشات البسيطة لمرة واحدة (مثل onboarding أو splash)، لا يتطلب Image.network تبعيات إضافية.
تتم إضافة CachedNetworkImage كتبعية قياسية لـ pub.dev. بعد التثبيت، الـ Widget جاهز للاستخدام. يتم تضمين flutter_cache_manager كتبعية انتقالية.
// pubspec.yaml
dependencies:
flutter:
sdk: flutter
cached_network_image: ^3.4.1
افتراضياً، يتم استخدام DefaultCacheManager بالإعدادات: TTL = 7 أيام، حد أقصى 200 ملف. لتغيير المعاملات العامة، يتم إنشاء نسخة CacheManager مخصصة مع Config، حيث يتم تجاوز maxAgeCacheObject و maxNrOfCacheObjects و repo.
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",
),
),
);
// استخدام مدير مخصص:
CachedNetworkImage(
cacheManager: customCacheManager,
imageUrl: url,
// ...
)
maxWidthBytes و maxHeightBytes — معاملات اختيارية للحد من حجم الملف المخزن مؤقتاً. هذا مفيد لتوفير مساحة القرص عندما تكون الصورة الأصلية أكبر من حجم الشاشة المطلوب.
الأسئلة الشائعة
CachedNetworkImage هو Widget خاص بـ Flutter لتحميل الصور من الشبكة مع تخزين مؤقت تلقائي على القرص. هو مطلوب لتوفير النطاق الترددي والعمل في وضع عدم الاتصال وعرض تقدم التحميل، وهو ما لا يوفره Image.network القياسي.
أضف cached_network_image: ^3.4.1 إلى قسم dependencies في ملف pubspec.yaml وقم بتشغيل flutter pub get. ثم استورد الحزمة في ملفك: import 'package:cached_network_image/cached_network_image.dart'.
أنشئ CacheManager مخصصاً مع Config حيث يتم تحديد معامل stalePeriod كـ Duration. مرر المدير الذي أنشأته إلى معامل cacheManager الخاص بـ Widget CachedNetworkImage. افتراضياً، يتم تخزين الملفات لمدة 7 أيام.
استدع DefaultCacheManager().emptyCache() للتنظيف الكامل لجميع الملفات. للإزالة فقط للمنتهية الصلاحية، استخدم cleanCache(). يتم تنظيف المدير المخصص عن طريق استدعاء emptyCache على نسخته.
نعم، CachedNetworkImage يدعم Android و iOS و Web و macOS و Windows و Linux. تضمن API موحدة سلوكاً متناسقاً عبر جميع المنصات، ويعمل التخزين المؤقت عبر flutter_cache_manager المُكيَّف لكل نظام تشغيل.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.