CachedNetworkImage: المفاهيم الأساسية وWidget ImageProvider

المؤلف: IT Sectr نُشر: 2026-05-05 وقت القراءة: 8 دق

CachedNetworkImage هو Widget خاص بـ Flutter لتحميل الصور من الشبكة وتخزينها مؤقتاً مع دعم مؤشرات التقدم والـ placeholders ومعالجة الأخطاء. وفقاً للصفحة الرسمية للحزمة، تعتمد المكتبة على flutter_cache_manager وتوفر تخزيناً مؤقتاً تلقائياً على القرص مع TTL قابل للتكوين. CachedNetworkImage هو الحل المعياري لتحميل الصور في تطبيقات Flutter مع التخزين المؤقت.

النقاط الرئيسية

  • CachedNetworkImage — Widget خاص بـ Flutter لتحميل الصور من الشبكة وتخزينها مؤقتاً مع إدارة تلقائية للذاكرة المؤقتة.
  • flutter_cache_manager — الحزمة الأساسية التي تنفذ التخزين المؤقت ثنائي المستوى (ملفات + ذاكرة) مع فهرسة SQLite.
  • ImageProvider — آلية Flutter للحصول غير المتزامن على الصور المفكوكة من أي مصدر.
  • مؤشر التقدم مدمج في الـ Widget ويعرض نسبة التحميل عبر معامل builder progressIndicatorBuilder.
  • معالجة الأخطاء — يظهر الـ Widget خطأ errorWidget عند فشل التحميل، مستبدلاً الصورة المعطوبة بقالب بديل.

ما هو CachedNetworkImage؟

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

يستخدم Flutter نظام تخزين مؤقت ثنائي المستوى: ImageCache (ذاكرة) و flutter_cache_manager (قرص + SQLite). ImageCache هو ذاكرة مؤقتة عالمية للصور المفكوكة بحدود من حيث العدد (افتراضياً 1000) والحجم (افتراضياً 100 ميجابايت). يدير flutter_cache_manager الملفات على القرص وبياناتها الوصفية.

تسلسل البحث

عندما يتلقى CachedNetworkImage طلب صورة، يتحقق أولاً من ImageCache الخاص بـ Flutter — إذا كانت الصورة قد فُكّت بالفعل في الذاكرة، يتم عرضها فوراً. في حالة عدم وجودها في الذاكرة المؤقتة، يتم التحقق من القرص عبر flutter_cache_manager: يقوم استعلام SQLite بالتحقق من وجود الملف في الذاكرة المؤقتة وما إذا كان TTL قد انتهى. إذا كان الملف محدثاً — يُقرأ من القرص ويُفك ويعرض. إذا كان الملف مفقوداً أو انتهى TTL — يتم إجراء طلب HTTP.

  • ImageCache — ذاكرة مؤقتة عالمية لـ Flutter، 1000 عنصر / 100 ميجابايت افتراضياً
  • flutter_cache_manager — SQLite + نظام ملفات، TTL 7 أيام
  • تحميل HTTP — يتم عبر حزمة http أو HttpClient مخصص

تنظيف الذاكرة المؤقتة

يوفر DefaultCacheManager طرق emptyCache() (تنظيف كامل)، cleanCache() (إزالة المنتهية فقط) و clearCacheWithAge() بتاريخ مخصص. يتم تنظيف ImageCache تلقائياً عند ضغط الذاكرة أو يدوياً عبر imageCache.clear().

هندسة Widget CachedNetworkImage

تم بناء CachedNetworkImage على تركيب Widgets Flutter القياسية. يستخدم التنفيذ الداخلي ImageProvider للتحميل غير المتزامن و StatefulWidget لإدارة دورة الحياة.

المعاملات الرئيسية

imageUrl — معامل إلزامي، رابط الصورة (String أو Uri). placeholder — Widget يظهر أثناء التحميل. errorWidget — Widget عند خطأ التحميل. progressIndicatorBuilder — Builder يستقبل السياق والرابط و DownloadProgress مع حقلي totalSize و downloadedSize.

ImageProvider

CachedNetworkImageProvider — تطبيق ImageProvider يعيد CachedNetworkStreamImage الذي يدير التحميل والتخزين المؤقت. يتكامل المزود مع ImageCache الخاص بـ Flutter ويدعم جميع إمكانيات ImageProvider القياسية: القياس والتمركز والتكرار.

تكوين flutter_cache_manager

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 في Dart

يوفر CachedNetworkImage طريقتين رئيسيتين للتحميل: Widget CachedNetworkImage و CachedNetworkImageProvider للسيناريوهات المخصصة.

التحميل الأساسي مع Placeholder

CachedNetworkImage — الطريقة الرئيسية. يكفي تمرير imageUrl و placeholder. يعرض الـ Widget تلقائياً الـ placeholder حتى اكتمال التحميل ثم يستبدله بالصورة.

dart
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.

dart
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

CachedNetworkImageProvider — مزود لـ Image أو DecorationImage دون استخدام Widget CachedNetworkImage. مفيد عند العمل مع BoxDecoration أو FadeInImage أو Widgets صور مخصصة.

dart
Container(
    decoration: BoxDecoration(
        image: DecorationImage(
            image: CachedNetworkImageProvider(
                "https://example.com/bg.jpg",
                maxWidthBytes: 2048,
                maxHeightBytes: 2048,
            ),
            fit: BoxFit.cover,
        ),
    ),
)

ImageBuilder والمعالجة المخصصة

يسمح المعامل imageBuilder في CachedNetworkImage بتجاوز Widget Image القياسي بتطبيق مخصص. بدلاً من عرض Image مباشرة، يمكنك استخدام Container مع زخرفة أو ClipRRect للقص أو Ink.image لتأثيرات التموج. يستقبل imageBuilder السياق و ImageProvider للصورة الجاهزة، مما يمنح تحكماً كاملاً في العرض.

معاملات إضافية: memCacheWidth و memCacheHeight يحددان حجم الصورة المخزنة مؤقتاً في RAM، مما يقلل الحمل على ImageCache الخاص بـ Flutter. cacheKey يسمح بتعيين مفتاح ذاكرة مؤقتة مخصص بدلاً من الرابط، وهو مفيد للصور ذات رموز التفويض في الرابط (تتغير معاملات الاستعلام مع كل طلب لكن المحتوى يبقى نفسه).

CachedNetworkImage مقابل Image.network القياسي

Widget Image.network القياسي يقوم بتحميل الصورة في كل إعادة بناء للـ Widget دون حفظ على القرص. يضيف CachedNetworkImage التخزين المؤقت للملفات ومؤشرات التقدم ومعالجة الأخطاء، لكنه يضيف تبعية لـ flutter_cache_manager و SQLite.

المعيارImage.networkCachedNetworkImage
ذاكرة تخزين مؤقتة على القرصلا (ذاكرة Flutter المؤقتة فقط)نعم (SQLite + ملفات)
مؤشر التقدملاprogressIndicatorBuilder
Widget الخطأPlaceholder أحمر فقط في وضع التصحيحerrorWidget مخصص
TTL الذاكرة المؤقتةغير قابل للتطبيققابل للتكوين (7 أيام افتراضياً)
التبعياتلا شيء (مدمج في Flutter)cached_network_image + flutter_cache_manager + sqflite
الوصول دون اتصاللانعم (مع الملفات المحملة مسبقاً)
حجم البناء0 كيلوبايت إضافية~300 كيلوبايت إضافية

للمشاريع التي تكون فيها القدرة على العمل دون اتصال وتوفير النطاق الترددي مهمة، فإن CachedNetworkImage هو الخيار الواضح. للشاشات البسيطة لمرة واحدة (مثل onboarding أو splash)، لا يتطلب Image.network تبعيات إضافية.

إعداد CachedNetworkImage في مشروع Flutter

تتم إضافة CachedNetworkImage كتبعية قياسية لـ pub.dev. بعد التثبيت، الـ Widget جاهز للاستخدام. يتم تضمين flutter_cache_manager كتبعية انتقالية.

dart
// pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  cached_network_image: ^3.4.1

افتراضياً، يتم استخدام DefaultCacheManager بالإعدادات: TTL = 7 أيام، حد أقصى 200 ملف. لتغيير المعاملات العامة، يتم إنشاء نسخة CacheManager مخصصة مع Config، حيث يتم تجاوز maxAgeCacheObject و maxNrOfCacheObjects و repo.

dart
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 ولماذا هو مطلوب؟

CachedNetworkImage هو Widget خاص بـ Flutter لتحميل الصور من الشبكة مع تخزين مؤقت تلقائي على القرص. هو مطلوب لتوفير النطاق الترددي والعمل في وضع عدم الاتصال وعرض تقدم التحميل، وهو ما لا يوفره Image.network القياسي.

كيف أضيف CachedNetworkImage إلى مشروع Flutter؟

أضف 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 أيام.

كيف أمسح ذاكرة CachedNetworkImage المؤقتة؟

استدع DefaultCacheManager().emptyCache() للتنظيف الكامل لجميع الملفات. للإزالة فقط للمنتهية الصلاحية، استخدم cleanCache(). يتم تنظيف المدير المخصص عن طريق استدعاء emptyCache على نسخته.

هل يعمل CachedNetworkImage على جميع منصات Flutter؟

نعم، CachedNetworkImage يدعم Android و iOS و Web و macOS و Windows و Linux. تضمن API موحدة سلوكاً متناسقاً عبر جميع المنصات، ويعمل التخزين المؤقت عبر flutter_cache_manager المُكيَّف لكل نظام تشغيل.

الملخص

  • CachedNetworkImage هو الحل المعياري لتحميل الصور مع التخزين المؤقت في Flutter مع أكثر من 4,000 إعجاب على pub.dev.
  • التخزين المؤقت ثنائي المستوى (ImageCache الخاص بـ Flutter + ملفات عبر SQLite) يقلل من طلبات الشبكة ويسرع العرض.
  • progressIndicatorBuilder يسمح بعرض نسبة التحميل للصور الكبيرة والاتصالات البطيئة.
  • CacheManager مخصص يمنح تحكماً كاملاً في TTL وعدد الملفات ومسار التخزين.
  • CachedNetworkImageProvider يعمل مع DecorationImage و BoxDecoration، مما يوسع حالات الاستخدام.
  • الوصول دون اتصال إلى الصور المحملة مسبقاً هو ميزة رئيسية مقارنة بـ Image.network القياسي.
  • عبر المنصات — قاعدة كود واحدة تعمل على جميع منصات Flutter الست دون تغييرات.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا