يمكن تغيير بعض إعدادات الجهاز أثناء تشغيل التطبيق. وتشمل هذه الإعدادات على سبيل المثال لا الحصر ما يلي:
- حجم عرض التطبيق
- اتجاه الشاشة
- حجم الخط وعرضه
- اللغة
- الوضع الداكن مقابل الوضع الفاتح
- مدى توفّر لوحة المفاتيح
تحدث معظم تغييرات الإعدادات هذه بسبب تفاعل المستخدم. على
سبيل المثال، يؤدي تدوير الجهاز أو طيّه إلى تغيير مساحة الشاشة
المتاحة لتطبيقك. وبالمثل، يؤدي تغيير إعدادات الجهاز، مثل حجم الخط،
أو اللغة أو المظهر المفضّل، إلى تغيير القيم المقابلة لها في
Configuration عنصر.
تتطلب هذه المَعلمات عادةً تغييرات كبيرة بما يكفي في واجهة مستخدم تطبيقك، ما يمنح نظام Android الأساسي آلية مصممة خصيصًا للتعامل معها عند تغييرها.
هذه الآلية هي إعادة إنشاء Activity.
إعادة إنشاء `Activity`
يعيد النظام إنشاء Activity عند حدوث تغيير في الإعدادات. ولإجراء ذل
ك، يستدعي النظام onDestroy ويزيل مثيل Activity
الحالي. بعد ذلك، ينشئ النظام مثيلاً جديدًا باستخدام onCreate، ويتم تهيئة مثيل
Activity الجديد هذا بالإعدادات الجديدة والمعدَّلة. ويعني ذلك أيضًا أنّ النظام يعيد إنشاء واجهة المستخدم باستخدام الإعدادات الجديدة.
عادةً ما يكون Activity بمثابة مضيف للعناصر المركّبة. عند إعادة إنشاء Activity، يعيد Compose أيضًا إنشاء واجهة المستخدم باستخدام قيم الإعدادات الجديدة.
يساعد سلوك إعادة الإنشاء تطبيقك على التكيّف مع الإعدادات الجديدة من خلال إعادة تحميل تطبيقك تلقائيًا باستخدام موارد بديلة تتطابق مع إعدادات الجهاز الجديدة.
مثال على إعادة الإنشاء
لنفترض أنّ هناك دالة مركّبة تعرض عنوانًا ثابتًا باستخدام مصدر السلاسل النصية:
// In the res/values/strings.xml file // <string name="compose">Jetpack Compose</string> // In your Compose code Text( text = stringResource(R.string.compose) )
عند إنشاء Activity، يقرأ العنصر المركّب Text الإعدادات الحالية (مثل اللغة) ويحلّ مورد السلسلة المناسب.
إذا تغيّرت اللغة، يعيد النظام إنشاء النشاط. وعند حدوث ذلك، يعيد Compose إنشاء واجهة المستخدم. وبما أنّ stringResource يقرأ من الإعدادات الحالية، يتم تعديل العنوان تلقائيًا ليصبح القيمة المترجَمة الصحيحة.
تؤدي عملية إعادة الإنشاء أيضًا إلى محو أي حالة يتم الاحتفاظ بها كحقول في Activity.
للاحتفاظ بحالة واجهة المستخدم عند تغيير الإعدادات، استخدِم أنماط إدارة الحالة المقترَحة. استخدِم ViewModel للبيانات ومنطق النشاط التجاري، واستخدِم rememberSaveable للحالة على مستوى واجهة المستخدم. باستخدام هذه الآليات، تظل حالتك محفوظة أثناء إعادة إنشاء Activity، بينما يتم تعديل واجهة المستخدم لتعكس الإعدادات الجديدة.
لمزيد من المعلومات عن حفظ الحالة في Compose، يُرجى الاطّلاع على مقالة حفظ حالة واجهة المستخدم في Compose.
توقعات المستخدمين
يتوقع مستخدم التطبيق الاحتفاظ بالحالة. إذا كان المستخدم يملأ نموذجًا وفتح تطبيقًا آخر في وضع النوافذ المتعددة للرجوع إلى معلومات، فستكون تجربة المستخدم سيئة إذا عاد إلى نموذج تم محوه أو إلى مكان آخر في التطبيق بالكامل. بصفتك مطوّرًا، عليك توفير تجربة مستخدم متّسقة عند تغيير الإعدادات وإعادة إنشاء النشاط.
للتحقّق مما إذا تم الاحتفاظ بالحالة في تطبيقك، يمكنك تنفيذ إجراءات تؤدي إلى تغيير الإعدادات أثناء تشغيل التطبيق في المقدّمة وأثناء تشغيله في الخلفية. وتتضمن هذه الإجراءات ما يلي:
- تدوير الجهاز
- تفعيل وضع النوافذ المتعددة
- تغيير حجم التطبيق أثناء استخدام وضع النوافذ المتعددة أو نافذة ذات شكل حر
- طي جهاز قابل للطي يتضمّن شاشات متعددة
- تغيير مظهر النظام، مثل الوضع الداكن مقابل الوضع الفاتح
- تغيير حجم الخط
- تغيير لغة النظام أو التطبيق
- ربط لوحة مفاتيح خارجية أو قطع الاتصال بها
- ربط جهاز إرساء أو قطع الاتصال به
هناك عدة طرق يمكنك اتّباعها للاحتفاظ بالحالة ذات الصلة أثناء إعادة إنشاء Activity. ويعتمد الخيار الذي يجب استخدامه على نوع الحالة التي تريد الاحتفاظ بها:
- التخزين المستمر المحلي للتعامل مع إيقاف العملية نهائيًا للبيانات المعقدة أو الكبيرة.
تشمل مساحة التخزين المحلية المستمرة قواعد البيانات أو
DataStore. - العناصر المحتفظ بها، مثل
ViewModel، للتعامل مع الحالة المرتبطة بواجهة المستخدم في الذاكرة أثناء استخدام المستخدم للتطبيق بنشاط rememberSaveableللاحتفاظ بحالة واجهة المستخدم المؤقتة عند تغيير الإعدادات وإيقاف العملية نهائيًا من قِبل النظام. هذا مناسب للحالة التي تعتمد على بيانات أدخلها المستخدم أو موضع التمرير أو التنقّل ولكنها لا تنتمي إلىViewModel.
للاطّلاع على واجهات برمجة التطبيقات لكل من هذه الحالات بالتفصيل، ومتى يكون استخدام كل منها مناسبًا، يُرجى الاطّلاع على مقالة حفظ حالات واجهة المستخدم.
تقييد إعادة إنشاء النشاط
يمكنك منع إعادة إنشاء النشاط تلقائيًا عند حدوث تغييرات معيّنة في الإعدادات. في التطبيقات الحديثة التي تستخدم Compose فقط، تتم إعادة إنشاء واجهة المستخدم في كلتا الحالتَين، ولكن يُنصح بالتعامل مع تغيير الإعدادات مباشرةً.
تؤدي تغييرات الإعدادات تلقائيًا إلى إجبار النظام على محو `Activity` وإعادة إنشائه، بما في ذلك واجهة المستخدم وأي عناصر مشتقة من `Activity`. إذا أعلنت أنّ `Activity` يتعامل مع تغيير الإعدادات بنفسه، يمنع النظام ذلك. بدلاً من ذلك، يتم تعديل عنصر Configuration فقط، ويعيد Compose إنشاء واجهة المستخدم باستخدام القيم الجديدة.
يوفّر التعامل مع تغييرات الإعدادات مباشرةً في Compose عدة مزايا:
- تحسين الأداء: إنّ إعادة إنشاء واجهة المستخدم أقل تكلفة من دورة إعادة إنشاء `Activity` كاملة، خاصةً بالنسبة إلى التغييرات الطفيفة.
- الرسوم المتحركة السلسة: إنّ تجنُّب إعادة تشغيل `Activity` يتيح لك تشغيل رسوم متحركة مستمرة عند تغيير الإعدادات، مثل عمليات الانتقال السلسة في التنسيق أثناء تدوير الجهاز.
- الاحتفاظ بالحالة: إنّ الاحتفاظ بمثيل `Activity` يقلّل من خطر فقدان حالة واجهة المستخدم المؤقتة أثناء حدث مثل تدوير الشاشة. ملاحظة: لا يزال عليك التعامل مع الاحتفاظ بالحالة عند إيقاف العملية نهائيًا من قِبل النظام.
لإيقاف إعادة إنشاء النشاط عند حدوث تغييرات معيّنة في الإعدادات،
أضِف نوع الإعداد إلى android:configChanges في
<activity> في ملف AndroidManifest.xml. تظهر القيم المحتمَلة
في مستندات السمة android:configChanges.
يوقف رمز البيان التالي إعادة إنشاء Activity لـ MyActivity عند
تغيير اتجاه الشاشة ومدى توفّر لوحة المفاتيح:
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
الاستجابة لتغييرات الإعدادات
يتيح Jetpack Compose لتطبيقك الاستجابة بسهولة أكبر لتغييرات الإعدادات.
ومع ذلك، إذا أوقفت إعادة إنشاء Activity لجميع تغييرات الإعدادات التي يمكن إيقافها، سيظل على تطبيقك التعامل مع تغييرات الإعدادات بشكل صحيح.
يتوفّر عنصر Configuration في تسلسل Compose UI الهرمي باستخدام
التركيبة المحلية LocalConfiguration. عندما يتغيّر، تتم إعادة إنشاء الدوال المركّبة التي تقرأ من LocalConfiguration.current. لمزيد من
المعلومات عن طريقة عمل التركيبات المحلية، يُرجى الاطّلاع على مقالة البيانات ذات النطاق المحلي
باستخدام CompositionLocal.
مثال
في المثال التالي، تعرض دالة مركّبة تاريخًا بتنسيق معيّن.
يستجيب العنصر المركّب لتغييرات إعدادات اللغة في النظام من خلال استدعاء
ConfigurationCompat.getLocales باستخدام LocalConfiguration.current.
@Composable
fun DateText(year: Int, dayOfYear: Int) {
val dateTimeFormatter = DateTimeFormatter.ofPattern(
"MMM dd",
ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
)
Text(
dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
)
}
لتجنُّب إعادة إنشاء Activity عند تغيير اللغة، يجب أن يرفض Activity الذي يستضيف رمز Compose تغييرات إعدادات اللغة. لإجراء ذلك، اضبط android:configChanges على locale|layoutDirection.
تغييرات الإعدادات: المفاهيم الأساسية وأفضل الممارسات
في ما يلي المفاهيم الأساسية التي عليك معرفتها عند العمل على تغييرات الإعدادات:
- الإعدادات: تحدّد إعدادات الجهاز كيفية عرض واجهة المستخدم للمستخدم، مثل حجم عرض التطبيق أو اللغة أو مظهر النظام. في Compose، يمكنك الوصول إلى قيم الإعدادات باستخدام
LocalConfiguration. - تغييرات الإعدادات: تتغيّر الإعدادات من خلال تفاعل المستخدم. على سبيل المثال، قد يغيّر المستخدم إعدادات الجهاز أو طريقة تفاعله فعليًا مع الجهاز. لا توجد طريقة لمنع تغييرات الإعدادات.
- إعادة إنشاء
Activity: تؤدي تغييرات الإعدادات إلى إعادة إنشاءActivityتلقائيًا. هذه آلية مضمّنة لإعادة تهيئة حالة التطبيق للإعدادات الجديدة. - إزالة
Activity: تؤدي إعادة إنشاءActivityإلى إجبار النظام على إزالة مثيلActivityالقديم وإنشاء مثيل جديد بدلاً منه. أصبح المثيل القديم قديمًا الآن. تجنَّب الاحتفاظ بمراجع للكائنات ذات النطاق المحدّد بدورة الحياة خارج نطاقها المقصود. - الحالة: لا تكون الحالة في مثيل
Activityالقديم موجودة في مثيلActivityالجديد، لأنّهما مثيلا كائن مختلفان. بدلاً من ربط الحالة بـ `Activity`، استخدِم واجهات برمجة التطبيقات المقترَحة للاحتفاظ بحالة التطبيق والمستخدم كما هو موضّح في حفظ حالات واجهة المستخدم. - إيقاف الميزة: يتطلب إيقاف إعادة إنشاء النشاط لنوع معيّن من تغييرات الإعدادات أن يحرص تطبيقك على تعديل نفسه بشكل صحيح استجابةً للإعدادات الجديدة.
لتقديم تجربة مستخدم جيدة، ننصحك باتّباع أفضل الممارسات التالية:
- الاستعداد لتغييرات الإعدادات المتكررة: لا تفترض أنّ تغييرات الإعدادات نادرة أو لا تحدث أبدًا، بغض النظر عن مستوى واجهة برمجة التطبيقات أو شكل الجهاز أو مجموعة أدوات واجهة المستخدم. عندما يتسبب المستخدم في تغيير الإعدادات، يتوقع أن يتم تعديل التطبيقات وأن تستمر في العمل بشكل صحيح باستخدام الإعدادات الجديدة.
- الاحتفاظ بالحالة: لا تفقد حالة المستخدم عند إعادة إنشاء
Activity. احتفِظ بالحالة كما هو موضّح في حفظ حالات واجهة المستخدم باستخدام واجهات برمجة التطبيقات مثلViewModelوrememberSaveable. - تجنُّب إيقاف الميزة كحل سريع: لا توقف إعادة إنشاء
Activityكاختصار لتجنُّب فقدان الحالة. يتطلب إيقاف إعادة إنشاء النشاط الوفاء بوعد التعامل مع التغيير، ولا يزال بإمكانك فقدان الحالة بسبب إعادة إنشاءActivityمن تغييرات الإعدادات الأخرى أو إيقاف العملية أو إغلاق التطبيق. من المستحيل إيقاف إعادة إنشاءActivityبالكامل. احتفِظ بالحالة كما هو موضّح في مقالة حفظ حالات واجهة المستخدم. - عدم تجنُّب تغييرات الإعدادات: لا تفرض قيودًا على الاتجاه،
نسبة العرض إلى الارتفاع أو إمكانية تغيير الحجم لتجنُّب تغييرات الإعدادات و
Activityإعادة الإنشاء. يؤثر ذلك سلبًا في المستخدمين الذين يريدون استخدام تطبيقك بالطريقة المفضّلة لديهم.
التعامل مع تغييرات الإعدادات المستندة إلى الحجم
يمكن أن تحدث تغييرات الإعدادات المستندة إلى الحجم في أي وقت، ويكون حدوثها أكثر احتمالاً عند تشغيل تطبيقك على جهاز بشاشة كبيرة حيث يمكن للمستخدمين تفعيل وضع النوافذ المتعددة. ويتوقعون أن يعمل تطبيقك بشكل جيد في هذه البيئة.
هناك نوعان عامّان من تغييرات الحجم: كبيرة وغير كبيرة. تغيير الحجم الكبير هو تغيير يتم فيه تطبيق مجموعة مختلفة من الموارد البديلة على الإعدادات الجديدة بسبب اختلاف في حجم الشاشة، مثل العرض أو الارتفاع أو أصغر عرض. تشمل هذه الموارد تلك التي يحدّدها التطبيق بنفسه وتلك من أي من مكتباته.
تقييد إعادة إنشاء النشاط عند حدوث تغييرات في الإعدادات المستندة إلى الحجم
عند إيقاف إعادة إنشاء Activity عند حدوث تغييرات في الإعدادات المستندة إلى الحجم، لا يعيد النظام إنشاء Activity. بدلاً من ذلك، يتلقّى النظام استدعاءً لـ
Activity.onConfigurationChanged. تتم إعادة إنشاء أي عناصر مركّبة تقرأ LocalConfiguration.current تلقائيًا لتعكس الحجم الجديد.
يتم إيقاف إعادة إنشاء Activity عند حدوث تغييرات في الإعدادات المستندة إلى الحجم عندما
يكون لديك
android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"
في ملف البيان.
مراجع إضافية
لمزيد من المعلومات عن التعامل مع تغييرات الإعدادات، يُرجى الاطّلاع على المراجع الإضافية التالية: