يمكن أن تتغيّر بعض إعدادات الجهاز أثناء تشغيل التطبيق. وتشمل هذه الحالات، على سبيل المثال لا الحصر:
- حجم عرض التطبيق
- اتجاه الشاشة
- حجم الخط ووزنه
- اللغة
- الوضع الداكن مقابل الوضع الفاتح
- توفُّر لوحة المفاتيح
تحدث معظم تغييرات الإعدادات هذه بسبب تفاعل المستخدم. على سبيل المثال، يؤدي تدوير الجهاز أو طيّه إلى تغيير مساحة الشاشة المتاحة لتطبيقك، كما أنّ تغيير إعدادات الجهاز، مثل حجم الخط أو اللغة أو المظهر المفضّل، يؤدي إلى تغيير القيم الخاصة بها في العنصر Configuration.
تتطلّب هذه المَعلمات عادةً تغييرات كبيرة بما يكفي في واجهة مستخدم تطبيقك،
لذا يتضمّن نظام Android الأساسي آلية مصمَّمة خصيصًا للتعامل مع هذه التغييرات.
هذه الآلية هي إعادة إنشاء 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 فقط، تتم إعادة إنشاء واجهة المستخدم في كلتا الحالتين، ولكن يُنصح بالتعامل مع تغيير الإعدادات مباشرةً.
بشكلٍ تلقائي، يؤدي تغيير الإعداد إلى إجبار النظام على محو النشاط وإعادة إنشائه، بما في ذلك واجهة المستخدم وأي عناصر مشتقة من النشاط. إذا أعلنت أنّ نشاطك يتعامل مع تغيير الإعدادات بنفسه، سيمنع النظام ذلك. بدلاً من ذلك، يتم تعديل العنصر Configuration فقط، ويعيد Compose إنشاء واجهة المستخدم باستخدام القيم الجديدة.
تتوفّر عدة مزايا عند التعامل مع تغييرات الإعدادات مباشرةً في Compose:
- تحسين الأداء: إعادة إنشاء واجهة المستخدم أقل تكلفة من دورة إعادة إنشاء النشاط بالكامل، خاصةً عند إجراء تغييرات بسيطة.
- الصور المتحركة السلسة: يتيح لك تجنُّب إعادة تشغيل النشاط عرض صور متحركة متواصلة عند إجراء تغييرات في الإعدادات، مثل عمليات الانتقال السلسة بين التنسيقات عند تدوير الجهاز.
- الحفاظ على الحالة: يؤدي الاحتفاظ بنسخة 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">
Android 17
بدءًا من Android 17 (المستوى 37 من واجهة برمجة التطبيقات)، لن يعيد النظام تشغيل الأنشطة تلقائيًا عند إجراء عدة تغييرات في الإعدادات لا تتطلّب عادةً إعادة إنشاء واجهة المستخدم بالكامل.
بدلاً من ذلك، تظل الأنشطة نشطة وتتلقّى التحديثات من خلال
الدالة onConfigurationChanged().
تشمل تغييرات الإعدادات المحدّدة ما يلي:
CONFIG_KEYBOARDCONFIG_KEYBOARD_HIDDENCONFIG_NAVIGATIONCONFIG_TOUCHSCREENCONFIG_COLOR_MODECONFIG_UI_MODE(فقط عند تغيير وضع واجهة المستخدم إلىUI_MODE_TYPE_DESKأو منUI_MODE_TYPE_DESKإلى نوع آخر)
إذا كان تطبيقك يعتمد على إعادة التشغيل الكاملة لإعادة تحميل الموارد لهذه التغييرات، عليك الآن الموافقة صراحةً على السلوك القديم باستخدام السمة android:recreateOnConfigChanges في ملف البيان.
تتيح لك السمة تحديد تغييرات الضبط التي يجب أن تؤدي إلى إيقاف النشاط بالكامل وتدميره وإعادة إنشائه، على سبيل المثال:
<activity
android:name=".MyActivity"
android:recreateOnConfigChanges="keyboard|keyboardHidden|navigation|colorMode|touchscreen|...">
...
</activity>
الاستجابة للتغييرات في الإعدادات
تتيح Jetpack Compose لتطبيقك الاستجابة بسهولة أكبر لتغييرات الإعدادات.
ومع ذلك، إذا أوقفت إعادة إنشاء Activity لجميع تغييرات الإعدادات
حيثما أمكن ذلك، يجب أن يتعامل تطبيقك مع تغييرات الإعدادات بشكل صحيح.
يتوفّر العنصر Configuration في التسلسل الهرمي لواجهة Compose UI مع
العنصر المحلي LocalConfiguration. وعندما تتغيّر، تتم إعادة إنشاء الدوال المركّبة التي تقرأ من LocalConfiguration.current. لمزيد من المعلومات حول طريقة عمل البيانات المحلية في Composition، يمكنك الاطّلاع على البيانات ذات النطاق المحلي باستخدام 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" في ملف البيان.
مراجع إضافية
لمزيد من المعلومات حول التعامل مع تغييرات الإعدادات، يُرجى الاطّلاع على المراجع الإضافية التالية: