استخدام المعزلات المتعددة
بدلاً من الخيوط (threads)، يتم تنفيذ كود Dart داخل المعزلات (isolates). لكل معزل ذاكرة خاصة به، مما يضمن عدم إمكانية الوصول إلى حالة أي معزل من معزل آخر.
يمكن الوصول إلى Isar من عدة معزلات في نفس الوقت، وحتى المراقبين (watchers) يعملون عبر المعزلات. في هذا الدليل، سنستعرض كيفية استخدام Isar في بيئة متعددة المعزلات.
متى نستخدم معزلات متعددة؟
يتم تنفيذ المعاملات (transactions) في Isar بشكل متوازٍ حتى لو كانت تعمل في نفس المعزل. في بعض الحالات، لا يزال من المفيد الوصول إلى Isar من معزلات متعددة.
السبب هو أن Isar يقضي وقتًا غير قليل في ترميز وفك ترميز البيانات من وإلى كائنات Dart. يمكنك التفكير في الأمر كترميز وفك ترميز JSON (لكنه أكثر كفاءة). هذه العمليات تعمل داخل المعزل الذي يتم من خلاله الوصول إلى البيانات، وتقوم بطبيعة الحال بحظر الكود الآخر في نفس المعزل. بمعنى آخر: يقوم Isar بجزء من العمل داخل معزل Dart الخاص بك.
إذا كنت تحتاج فقط لقراءة أو كتابة بضع مئات من الكائنات دفعة واحدة، فإن القيام بذلك في معزل واجهة المستخدم ليس مشكلة. ولكن بالنسبة للمعاملات الضخمة أو إذا كان خيط واجهة المستخدم مشغولاً بالفعل، فعليك التفكير في استخدام معزل منفصل.
مثال
أول شيء نحتاج إليه هو فتح Isar في المعزل الجديد. نظرًا لأن مثيل Isar مفتوح بالفعل في المعزل الرئيسي، فإن Isar.open() سيعيد نفس المثيل.
:::warning تأكد من توفير نفس المخططات (schemas) الموجودة في المعزل الرئيسي. وإلا ستحصل على خطأ. :::
compute() تبدأ معزلًا جديدًا في Flutter وتشغّل الدالة المحددة فيه.
void main() {
// فتح Isar في معزل واجهة المستخدم
final dir = await getApplicationDocumentsDirectory();
final isar = await Isar.openAsync(
schemas: [MessageSchema],
directory: dir.path,
name: 'myInstance',
);
// الاستماع إلى التغييرات في قاعدة البيانات
isar.messages.watchLazy(() {
print('لقد تغيرت الرسائل!');
});
// بدء معزل جديد وإنشاء 10000 رسالة
compute(createDummyMessages, 10000).then(() {
print('انتهى المعزل');
});
// بعد فترة:
// > لقد تغيرت الرسائل!
// > انتهى المعزل
}
// دالة سيتم تنفيذها في المعزل الجديد
Future createDummyMessages(int count) async {
// لا نحتاج إلى المسار هنا لأن المثيل مفتوح بالفعل
final dir = await getApplicationDocumentsDirectory();
final isar = await Isar.openAsync(
schemas: [PostSchema],
directory: dir.path,
name: 'myInstance',
);
final messages = List.generate(count, (i) => Message()..content = 'الرسالة $i');
// نستخدم المعاملات المتزامنة في المعزلات
isar.writeTxnSync(() {
isar.messages.insertAllSync(messages);
});
}
هناك بضع نقاط مثيرة للاهتمام في المثال أعلاه:
- تم استدعاء isar.messages.watchLazy() في معزل واجهة المستخدم ويتم إخطاره بالتغييرات القادمة من معزل آخر.
- يتم الرجوع إلى المثيلات بالاسم. الاسم الافتراضي هو default، لكن في هذا المثال قمنا بتعيينه إلى myInstance.
- استخدمنا معاملة متزامنة لإنشاء الرسائل. لا يمثل حظر المعزل الجديد مشكلة، والمعاملات المتزامنة أسرع قليلاً.
```