Kotlin / دليل حلول تحريري
تشخيص الإلغاء المتجاهل وتحديثات الحالة غير المرصودة
افصل ابتلاع إشارة الإلغاء وأعمار الكوروتينات غير المملوكة وجمع Flow الباردة ودمج StateFlow.
قاعدة معرفة للقراءة فقط · بلا تعليقات عامة
تعرّف على الأعراض
تستمر شاشة افتراضية في العمل بعد إغلاقها، ويبدو تدفق آخر كأنه لا يفعل شيئا، ويفوّت مراقب بطيء تغيرات حالة وسيطة. توصف جميع الأعراض بأنها أخطاء كوروتينات، لكن كلا منها يشير إلى عقد مختلف. افحص العمر والجمع ودلالات تسليم القيم بصورة منفصلة، قبل تبديل الموزعات أو إضافة تأخيرات.
افهم الأسباب المحتملة
- تشمل الاحتمالات نطاقا يعيش أطول من مالكه، وcatch واسعة تحول CancellationException إلى نجاح، وFlow باردة بلا جامع، وتعديلا مكانيا داخل حالة تدمج بالمساواة، أو تمثيل تدفق أحداث خطأ بوصفه حالة حالية. وقد تؤخر عملية حاجبة غير متعاونة الاستجابة للإلغاء أيضا.
تتبّع من ينشئ نطاق الكوروتينات ومن يلغيه
سجّل الطلب أو الشاشة أو مكون التطبيق المالك، والنطاق الذي ينشئه، والحدث الذي ينهي ذلك العمر. قد يتجاوز نطاق عام أو نطاق منفصل حديثا إلغاء المستدعي حتى عندما تحمل كل الدوال suspend. افحص علاقة الأبوة في Job وأي سياق بديل يُمرر صراحة. لا تعالج خلل الملكية باستدعاءات نوم اعتباطية. وإذا وجب أن يستمر العمل بعد الشاشة، فامنحه مالكا مقصودا على مستوى التطبيق أو مسار عمل دائم، ونتيجة ظاهرة للمنتج، بدلا من تركه يستمر بالمصادفة.
احفظ إشارة الإلغاء أثناء ترجمة الأخطاء
ابحث عند الحد المعني عن catch واسعة وأدوات شبيهة بـrunCatching وقيم بديلة تحوّل كل الإخفاقات إلى بيانات عادية. يعيد الجزء أدناه رمي الإلغاء أولا عمدا. وليس تطبيقا كاملا، ويتطلب سياق kotlinx.coroutines متوافقا. افحص بعد ذلك الحلقات الطويلة والاستدعاءات الحاجبة التي لا تتعلق ولا تفحص السياق النشط. الإلغاء تعاوني؛ فقد ينقل تغيير الموزّع عملية لا تستجيب من مكان إلى آخر دون جعلها قابلة للإلغاء. ولا تثبت المهلة أن أثرا خارجيا قد عُكس.
try {
loadOwnedData()
} catch (cancelled: kotlinx.coroutines.CancellationException) {
throw cancelled
} catch (failure: ExpectedLoadFailure) {
showDeclaredFailure(failure)
}
تمثل الأسماء عمليات وأنواع أخطاء خاصة بالتطبيق، لذلك فالجزء غير قابل للتشغيل. يوضح ترجمة ضيقة للإخفاقات، ولا يمثل تنفيذا جرى التحقق منه.
افحص هل تُنتَج القيم أو تُجمع أو تُدمج
تبدأ Flow الباردة منتجها عند الجمع، ولذلك قد يكون عدم حدوث عمل فوري عند إنشاء المسار سلوكا صحيحا. أما StateFlow فلها حالة حالية ودمج قائم على المساواة، وقد يتجاوز مشترك بطيء القيم الوسيطة. إذا كان كل حدث حجز مهما، فاستخدم تصميما يحفظ دلالات تسليم تلك الأحداث بدلا من توقع عمل حامل الحالة كسجل دائم. ولكائنات الحالة، تجنب تعديل قائمة داخلية مشتركة ثم إسناد القيمة الفعلية نفسها. انشر قيمة جديدة تحت مالك موثق، وأبق lambdas التحديث خالية من الآثار الخارجية.
Question: producer never starts
Inspect: cold Flow has an owned terminal collector
Question: intermediate states are skipped
Inspect: StateFlow equality/conflation and observer speed
Question: work survives owner cancellation
Inspect: Job parentage, broad catches, and cooperative checks
تحدد الخريطة فرضيات مختلفة. لا تتضمن نتيجة تشغيل مرصودة أو قيمة لضبط موزّع، ولا تضمن أن لكل عرض سببا وحيدا.
تحقق بأحداث عمر صريحة وجدولة مضبوطة
استخدم مشروعا معزولا بأدوات اختبار Kotlin والكوروتينات المعلنة له. ابدأ عملا مملوكا، وفعّل الإلغاء، وانتظر اكتماله قبل التوكيد على التنظيف. اجمع التدفق البارد وافحص قيمه المتوقعة. ومع StateFlow، افحص دلالات الحالة الحالية بدلا من مطالبة جامع بطيء برؤية كل حدث وسيط. استخدم مجدول إطار الاختبار المدعوم بدلا من افتراضات النوم اعتمادا على الساعة الفعلية حيث يناسب. سجّل نسخ المكتبة والنتائج الحقيقية؛ لا يملك هذا الدليل مترجما أو بيئة كوروتينات، ولذلك يعرض خطة مقترحة فقط.
تحقق من نجاح الإصلاح
يثبت الإصلاح الصحيح إلغاء المالك، والحفاظ على إشارات الإلغاء، وعقد تسليم التدفق المقصود، ضمن بيئة الاختبار المعزولة المعدة فعليا. افحص حالة الموارد والنتيجة التجارية النهائية، إلى جانب ترتيب السجلات. لا يدّعي الدليل نتيجة تشغيل أو توقيت أو سباق بين المشتركين.
امنع تكرار المشكلة
- راجع كل نطاق منشأ، وكل مترجم واسع للاستثناءات، وكل تحديث حالة مشتركة، وكل قرار مشاركة تدفق، من حيث الملكية والمعنى. افصل الحالة الحالية عن الأحداث الدائمة، وأبق دوال التحديث صرفة، واحفظ الإلغاء عند إدخال بدائل جديدة أو محولات لمزودين.