Flutter / واجهات شاملة وأدلة الأهداف / الدرس 16
قنوات المنصة وحدود الأذونات
نمذج الاستدعاءات الأصلية كعقود غير متزامنة قابلة للفشل وأبق قدرات المنصة خلف مهايئات صريحة.
في هذه الصفحة
أهداف الدرس
- تعبر الإضافة أكثر من حد دالة Dart
- عرّف أسماء القنوات والحمولات كبروتوكول
- حوّل النتيجة الأصلية إلى عقد تطبيق
تعبر الإضافة أكثر من حد دالة Dart
قد تشمل ميزة منصة شيفرة Dart وترميز قناة وتسجيلًا أصليا وواجهات المنصة وإعداد الأذونات وقرار المستخدم وقدرة الجهاز. يغطي نجاح المحلّل جزءا فقط من المسار. قبل اختيار إضافة راجع الأهداف المدعومة وتعليمات إعدادها ودلالات الفشل للإصدارات المختارة. نجاح الميزة على Android لا يثبت تنفيذها على iOS أو الويب. أبق الوصول للقدرة الأصلية خلف مهايئ صغير لتميّز بقية التطبيق بين المتاح وغير المتاح والمرفوض والفاشل دون استيراد تفاصيل المنصة في كل موضع.
عرّف أسماء القنوات والحمولات كبروتوكول
تشكل أسماء قنوات الدوال ومعرّفاتها بروتوكولا مشتركا مع التنفيذ الأصلي. اجعل الأسماء محددة النطاق لتجنب التصادم، ويجب أن تدعم أداة الترميز قيم الحمولة. وثّق الوحدات وقابلية الغياب وفئات الخطأ وسياسة التوافق كما في حدود الشبكة. لا تتحقق أنواع Dart الساكنة من القيمة المعادة أصليا. قد يعني null قدرة غير مدعومة أو قيمة مفقودة أو عيبا بحسب البروتوكول؛ فاختر معنى صريحا بدلا من فرض الصفر. وأبعد الاستدعاءات الأصلية عن build كي لا تكرر إعادة البناء طلب الإذن.
حوّل النتيجة الأصلية إلى عقد تطبيق
يستدعي المقتطف الأول قناة مصطنعة عمدا لنسبة البطارية. يفحص النطاق الرقمي ويبلغ عن البيانات الأصلية المعيبة بصورة مستقلة. لا يوجد طرف أصلي مقابل في الدورة، لذلك لا يثبت تشغيله تنفيذ قدرة صحيحا. تمثل MissingPluginException وPlatformException نتائج تكامل محتملة ينبغي للمهايئ ترجمتها بحسب عقد التطبيق. ولا يقدم المقتطف طريقة لتجاوز إذن أو استعلام جهاز حقيقي من بيئة التأليف. القناة توضيح لحد يتطلب عملا على الهدف.
import 'package:flutter/services.dart';
const batteryChannel = MethodChannel('example.learning/battery');
Future<int?> readBattery() async {
final value = await batteryChannel.invokeMethod<int>('readPercent');
if (value == null) return null;
if (value < 0 || value > 100) {
throw const FormatException('Invalid battery percentage');
}
return value;
}
A conforming native implementation returns null or an integer from 0 through 100.
لا يُقدّم معالج قناة أصلي ولا يُنفذ. يصف الناتج المتوقع عقد البروتوكول لا خرج جهاز مرصودا.
استخدم قدرة مزيفة لاختبار قرارات التطبيق
يوفر المقتطف الثاني اعتمادا ضيقا لقراءة البطارية وبديلًا مزيفا محدد النتائج. يمكن للنموذج اختبار عرض البطارية المنخفضة دون تسجيل أصلي أو عتاد. أضف بدائل لعدم التوافر والفشل عند الحاجة. هذا حد اختبار وليس دليلا على صحة ترميز القناة أو الواجهة الأصلية في الإنتاج. أبق اختبارات تكامل المنصة منفصلة ونفذها في بيئة هدف مصرح بها فقط. يمنع الفصل تحول اختبار وحدة مريح إلى ادعاء غير مدعوم عن ميزة جهاز.
abstract interface class BatteryReader { Future<int?> readPercent(); }
class FakeBattery implements BatteryReader {
FakeBattery(this.value);
final int? value;
@override Future<int?> readPercent() async => value;
}
Future<String> batteryLabel(BatteryReader reader) async {
final value = await reader.readPercent();
return value == null ? 'Unavailable' : '$value%';
}
// await batteryLabel(FakeBattery(25)) -> '25%'
The fake value 25 produces 25%; a null fake produces Unavailable.
يمثل المثال ربط التطبيق فقط. ولا يتحقق البديل من التسجيل الأصلي أو الأذونات أو توافق الترميز.
اطلب الأذونات في وقت مفهوم
اطلب الإذن حين يفهم المستخدم الميزة التي تحتاجه وما يحدث عند الرفض. قد تشمل حالات المنصة وصولا محدودا أو رفضا أو قيودا أو تغير الإعدادات، وليست دائما قيمة منطقية واحدة. اتبع توثيق المنصة والإضافة الحالي للهدف بدلا من تكرار الطلب مع كل بناء. احفظ بديلا مفيدا حيث يمكن. وعند استئناف التطبيق قد يكون الإذن تغير خارجه، فحدّث حالة القدرة عند حد دورة حياة مقصود دون تكرار أمر المستخدم الأصلي تلقائيا.
شخّص الحد الذي فشل فعلا
تحتاج معالجة قناة مفقودة وحمولة معيبة وإذن مرفوض وقدرة جهاز غائبة إلى حلول مختلفة. التقط أول استثناء ذي صلة والمنصة ومتغير البناء وإصدارات الإضافات واستدعاء مصطنعا مصغرا. راجع التسجيل والإعداد قبل تغيير منطق العمل غير المرتبط. وقد لا تطبق إعادة التحميل السريعة تغييرات الإعداد الأصلي، فاستخدم سير إعادة البناء الموثق في بيئة التطوير المصرح بها. ولا تجعل تنظيف ملفات البناء حلا عاما. تحقق من الميزة على كل هدف، بما فيه الرفض والتعافي، واحفظ اختبارات البدائل لسياسة التطبيق.
الأخطاء الشائعة وإصلاحها
تبلغ القناة MissingPluginException
- لماذا يحدث؟
- لا يوجد تنفيذ أصلي مقابل مسجل للهدف والدالة.
- كيف تصلحه؟
- افحص دعم الهدف والتسجيل وأسماء البروتوكول وإعادة البناء المطلوبة.
- كيف تتجنب تكراره؟
- احفظ مصفوفة قدرات الأهداف وعينة تكامل مصغرة.
يتكرر حوار الإذن على نحو مفاجئ
- لماذا يحدث؟
- يبدأ طلب الإذن من العرض أو منطق استئناف غير مميز.
- كيف تصلحه؟
- اطلبه من فعل ميزة صريح وحدّث الحالة بصورة منفصلة.
- كيف تتجنب تكراره؟
- اختبر البناء والاستئناف دون تفعيل المستخدم.
يُعتبر اختبار القدرة المزيفة تحققا أصليا
- لماذا يحدث؟
- لم تُختبر حدود المهايئ على الهدف.
- كيف تصلحه؟
- أبلغ عن اختبارات السياسة المزيفة منفصلة عن نتائج تكامل الهدف.
- كيف تتجنب تكراره؟
- سجّل التنفيذ المستعمل بدقة.
اختبر فهمك
1. هل تصبح بيانات البطارية null صفرا بالمئة تلقائيا؟
اعرض الحل المشروح
لا. الصفر قياس صحيح وله عواقب، بينما قد تعني null عدم التوافر ضمن البروتوكول. احفظ الفرق واعرض حالة عدم التوافر. وإذا سمح البروتوكول الأصلي بمعان أخرى فعرّفها واختبرها قبل الربط.
2. ماذا يثبت نجاح اختبار batteryLabel ببديل مزيف؟
اعرض الحل المشروح
يثبت ربط التطبيق نتيجة قارئ مقدمة بتسمية. ولا يثبت اسم الدالة الأصلية أو نوع الترميز أو تسجيل الإضافة أو الإذن أو سلوك العتاد. تحتاج هذه إلى أدلة مستقلة للمهايئ وتكامل الهدف.
أهم ما تعلمته
- تعبر الإضافة أكثر من حد دالة Dart
- شخّص الحد الذي فشل فعلا