يمكن أن تتغيّر بعض إعدادات الجهاز أثناء تشغيل التطبيق. ويشمل ذلك، على سبيل المثال لا الحصر:
- حجم عرض التطبيق
- اتجاه الشاشة
- حجم الخط ووزنه
- اللغة
- الوضع الداكن في مقابل الوضع الفاتح
- مدى توفّر لوحة المفاتيح
تحدث معظم تغييرات الإعدادات هذه بسبب بعض تفاعلات المستخدمين. على سبيل المثال، يؤدي تدوير الجهاز أو طيّه إلى تغيير مقدار المساحة المتوفّرة على الشاشة لتطبيقك. وبالمثل، يؤدي تغيير إعدادات الجهاز، مثل حجم الخط أو اللغة أو المظهر المفضّل، إلى تغيير قيمها في عنصر
Configuration
.
تتطلّب هذه المَعلمات عادةً تغييرات كبيرة بما يكفي في واجهة مستخدم تطبيقك
لكي تتضمّن منصة Android آلية مخصّصة لإجراء هذه التغييرات.
هذه الآلية هي Activity
إعادة إنشاء.
إعادة إنشاء الأنشطة
يعيد النظام إنشاء Activity
عند حدوث تغيير في الإعدادات. لإجراء ذلك، يُطلِق النظامonDestroy()
ويُزيل مثيل Activity
الحالي. بعد ذلك، يتم
إنشاء مثيل جديد باستخدام onCreate()
، ويتم
تهيئة مثيل Activity
الجديد بالإعدادات الجديدة المعدَّلة. ويعني ذلك أيضًا أنّ النظام
يعيد أيضًا إنشاء واجهة المستخدم باستخدام الإعدادات الجديدة.
يساعد سلوك إعادة الإنشاء تطبيقك على التكيّف مع الإعدادات الجديدة من خلال إعادة تحميل تطبيقك تلقائيًا باستخدام موارد بديلة تتطابق مع إعدادات الجهاز الجديدة.
مثال على الأنشطة الترفيهية
لنفترض أنّ TextView
يعرض عنوانًا ثابتًا باستخدام
android:text="@string/title"
، كما هو محدّد في ملف XML الخاص بالتنسيق. عند إنشاء العرض، يتم ضبط النص مرة واحدة فقط استنادًا إلى اللغة الحالية. في حال تغيّر
اللغة، يعيد النظام إنشاء النشاط. نتيجةً لذلك، يعيد النظام
إنشاء طريقة العرض ويُنشئها بالقيمة الصحيحة استنادًا إلى اللغة
الجديدة.
تؤدي عملية إعادة الإنشاء أيضًا إلى محو أي حالة محفوظة كحقول في
Activity
أو في أي من Fragment
أو View
أو عناصر أخرى مضمّنة فيه. ويعود سبب ذلك
إلى أنّ إعادة إنشاء Activity
تؤدي إلى إنشاء مثيل جديد تمامًا من Activity
وواجهة المستخدم. بالإضافة إلى ذلك، لم يعُد Activity
القديم مرئيًا أو صالحًا، لذا فإنّ أي
مراجع متبقية إليه أو إلى الكائنات التي يحتوي عليها قديمة. ويمكن أن تؤدي إلى
ظهور أخطاء وتسرُّب للذاكرة وأعطال.
توقعات المستخدمين
يتوقع مستخدم التطبيق الاحتفاظ بالحالة. إذا كان المستخدم يملؤ نموذجًا ويفتح تطبيقًا آخر في وضع النوافذ المتعدّدة للرجوع إلى المعلومات، ستكون تجربته سيئة إذا عاد إلى نموذج تم محو بياناته أو إلى مكان آخر في التطبيق بالكامل. بصفتك مطوّرًا، عليك تقديم تجربة مستخدم متّسقة من خلال تغييرات الإعدادات وإعادة إنشاء الأنشطة.
للتحقّق مما إذا كان يتم الاحتفاظ بالحالة في تطبيقك، يمكنك تنفيذ إجراءات تؤدي إلى تغييرات في الإعدادات سواء كان التطبيق في المقدّمة أو في الخلفية. وتتضمن هذه الإجراءات:
- تدوير الجهاز
- تفعيل وضع "نوافذ متعددة"
- تغيير حجم التطبيق أثناء تفعيل وضع "نوافذ متعددة" أو نافذة بتنسيق حر
- طي جهاز قابل للطي مزوّد بشاشات متعددة
- تغيير مظهر النظام، مثل الوضع الداكن مقابل الوضع الفاتح
- تغيير حجم الخط
- تغيير لغة النظام أو التطبيق
- توصيل لوحة مفاتيح جهاز أو فصلها
- توصيل قاعدة شحن أو فصلها
هناك ثلاث طرق أساسية يمكنك اتّباعها للحفاظ على الحالة ذات الصلة من خلال
Activity
إعادة الإنشاء. يعتمد نوع الحالة التي تريد
الحفاظ عليها على نوع العنصر:
- الثبات على الجهاز للتعامل مع حالات إنهاء العملية للبيانات المعقّدة أو الكبيرة
تشمل مساحة التخزين المحلية الدائمة قواعد البيانات أو
DataStore
. - العناصر المحفوظة، مثل نُسخ
ViewModel
لمعالجة الحالة المتعلّقة بواجهة المستخدم في الذاكرة أثناء استخدام المستخدم للتطبيق بشكل نشط - حالة النسخة المحفوظة للتعامل مع إنهاء العملية التي يبدأها النظام والحفاظ على الحالة المؤقتة التي تعتمد على إدخال المستخدم أو التنقّل
للاطّلاع على تفاصيل واجهات برمجة التطبيقات لكلّ من هذه الواجهات، ومعرفة الحالات التي يكون فيها استخدام كلّ منها مناسبًا، اطّلِع على مقالة حفظ حالات واجهة المستخدم.
حظر إعادة إنشاء الأنشطة
يمكنك منع إعادة إنشاء الأنشطة تلقائيًا لبعض تغييرات الإعدادات.
يؤدي إعادة إنشاء 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">
تؤدي بعض تغييرات الإعدادات دائمًا إلى إعادة تشغيل النشاط. ولا يمكنك إيقافه. على سبيل المثال، لا يمكنك إيقاف ميزة تغيير الألوان الديناميكية التي تم تقديمها في Android 12L (المستوى 32 من واجهة برمجة التطبيقات).
التفاعل مع تغييرات الإعدادات في نظام View
في نظام View
، عند حدوث تغيير في الإعدادات أدّى إلى
إيقاف إعادة إنشاء Activity
، يتلقّى النشاط طلبًا ل
Activity.onConfigurationChanged()
. تتلقّى أيضًا أيّ طرق عرض مرفقة دعوةً لتعديل View.onConfigurationChanged()
. بالنسبة إلى تغييرات الضبط التي
لم تُضفها إلى android:configChanges
، يُعيد النظام إنشاء النشاط
كالعادة.
تتلقّى طريقة الاستدعاء onConfigurationChanged()
عنصرًا
Configuration
يحدّد إعدادات الجهاز الجديدة. اقرأ
الحقول في عنصر Configuration
لتحديد الإعدادات الجديدة
التي تريدها. لإجراء التغييرات اللاحقة، عدِّل الموارد
التي تستخدمها في واجهتك. عندما يستدعي النظام هذه الطريقة، يتم تعديل عنصر
Resources
في نشاطك لعرض الموارد استنادًا إلى الإعدادات الجديدة. يتيح لك ذلك إعادة ضبط عناصر واجهة المستخدم بدون أن يعيد النظام
بدء نشاطك.
على سبيل المثال، تتحقّق عملية تنفيذ onConfigurationChanged()
التالية مما إذا كانت لوحة المفاتيح متاحة:
Kotlin
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Checks whether a keyboard is available
if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
} else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
}
}
Java
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a keyboard is available
if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
} else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
}
}
إذا لم تكن بحاجة إلى تعديل تطبيقك استنادًا إلى
تغييرات الإعدادات هذه، يمكنك عدم تنفيذ onConfigurationChanged()
بدلاً من ذلك. في هذه الحالة، سيستمر استخدام جميع الموارد المستخدَمة قبل تغيير الإعدادات،
ولن يؤدي ذلك إلا إلى تجنُّب إعادة تشغيل نشاطك. على سبيل المثال، قد لا يريد تطبيق التلفزيون
الاستجابة عند ربط لوحة مفاتيح بلوتوث أو فصلها.
الاحتفاظ بالحالة
عند استخدام هذه الطريقة، يجب الاحتفاظ بالحالة أثناء دورة حياة النشاط العادية. ويرجع ذلك إلى الأسباب التالية:
- التغييرات التي لا يمكن تجنُّبها: يمكن أن تؤدي تغييرات الإعدادات التي لا يمكنك منعها إلى إعادة تشغيل تطبيقك.
- إيقاف العملية نهائيًا: يجب أن يكون تطبيقك قادرًا على التعامل مع عملية الإيقاف نهائيًا التي يبدأها النظام. إذا خرج المستخدم من تطبيقك وأصبح في الخلفية، قد يُغلق النظام التطبيق.
الاستجابة لتغييرات الإعدادات في Jetpack Compose
يتيح Jetpack Compose لتطبيقك الاستجابة بسهولة أكبر لتغييرات الإعدادات.
ومع ذلك، في حال إيقاف Activity
إعادة إنشاء جميع تغييرات الإعدادات حيث يكون
ذلك ممكنًا، يجب أن يعالج تطبيقك
تغييرات الإعدادات بشكل صحيح.
يتوفّر العنصر Configuration
في التسلسل الهرمي لواجهة مستخدم "الكتابة" مع
تركيبة LocalConfiguration
المحلية. عند حدوث تغيير، تتم إعادة تركيب الدوال القابلة للتجميع التي تقرأ من LocalConfiguration.current
. للحصول على
معلومات عن آلية عمل متغيرات CompositionLocal، اطّلِع على البيانات على النطاق المحلي
باستخدام 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
الذي يستضيف
رمز الإنشاء تغييرات إعدادات اللغة. لإجراء ذلك، عليك
ضبط android:configChanges
على locale|layoutDirection
.
تغييرات الإعداد: المفاهيم الرئيسية وأفضل الممارسات
في ما يلي المفاهيم الأساسية التي يجب معرفتها عند العمل على تغييرات الإعدادات:
- الإعدادات: تحدِّد إعدادات الجهاز كيفية عرض واجهة المستخدم للمستخدم، مثل حجم عرض التطبيق أو اللغة أو مظهر النظام.
- تغييرات الضبط: تتغيّر الإعدادات من خلال تفاعل المستخدم. على سبيل المثال، قد يغيّر المستخدم إعدادات الجهاز أو طريقة تفاعله المادي مع الجهاز. لا تتوفّر طريقة لمنع تغييرات الضبط.
Activity
إعادة الإنشاء: تؤدي تغييرات الإعدادات إلى إعادة إنشاءActivity
تلقائيًا. هذه آلية مضمّنة لإعادة بدء حالة التطبيق من أجل الإعدادات الجديدة.Activity
destruction: يؤدي إعادة إنشاءActivity
إلى أن يُزيل النظام مثيلActivity
القديم وينشئ مثيلًا جديدًا بدلاً منه. أصبحت النسخة القديمة قديمة الآن. وتؤدي أي إشارات متبقية إليه إلى تسرب الذاكرة أو الأعطال أو الأعطال.- الحالة: لا تتوفّر الحالة في مثيل
Activity
القديم في مثيلActivity
الجديد، لأنّهما مثيلان مختلفان للعنصر. يجب الحفاظ على حالة التطبيق والمستخدم كما هو موضّح في حفظ حالات واجهة المستخدم. - إيقاف الميزة: يُعدّ إيقاف إعادة إنشاء الأنشطة لنوع من عمليات تغيير الإعدادات أحد التحسينات المحتملة. ويتطلّب ذلك أن يتم تحديث تطبيقك بشكل صحيح استجابةً للإعدادات الجديدة.
لتقديم تجربة إيجابية للمستخدم، اتّبِع أفضل الممارسات التالية:
- الاستعداد لإجراء تغييرات متكرّرة على الإعدادات: لا تفترض أنّ تغييرات الإعدادات نادرة أو لا تحدث أبدًا، بغض النظر عن مستوى واجهة برمجة التطبيقات أو شكل الجهاز أو مجموعة أدوات واجهة المستخدم. عندما يُجري أحد المستخدمين تغييرًا في الإعدادات، يتوقع أن يتم تحديث التطبيقات ويتوقع مواصلة العمل بشكل صحيح باستخدام الإعدادات الجديدة.
- الاحتفاظ بالحالة: لا تفقد حالة المستخدم عند
Activity
إعادة الإنشاء. يجب الاحتفاظ بالحالة كما هو موضّح في مقالة حفظ حالات واجهة المستخدم. - تجنُّب إيقاف الميزة كحل سريع: لا توقِف ميزة
Activity
إعادة الإنشاء كاختصار لتجنُّب فقدان الحالة. يتطلّب إيقاف ميزة إعادة إنشاء الأنشطة منك الوفاء بالوعد بمعالجة التغيير، ولا يزال بإمكانك فقدان الحالة بسبب إعادة إنشاءActivity
من تغييرات الإعدادات الأخرى أو إنهاء العملية أو إغلاق التطبيق. من المستحيل إيقاف ميزة إعادة إنشاءActivity
تمامًا. يجب الاحتفاظ بالحالة كما هو موضّح في مقالة حفظ حالات واجهة المستخدم. - تجنُّب تجنُّب تغييرات الضبط: لا تفرض قيودًا على الاتجاه أو
نسبة العرض إلى الارتفاع أو إمكانية تغيير الحجم لتجنُّب تغييرات الضبط و
Activity
إعادة الإنشاء. ويؤثر ذلك سلبًا في المستخدمين الذين يريدون استخدام تطبيقك بالطريقة المفضّلة لديهم.
التعامل مع تغييرات الإعدادات المستندة إلى الحجم
يمكن أن تحدث تغييرات الضبط المستندة إلى الحجم في أي وقت، ومن المرجّح أن تحدث عندما يتم تشغيل تطبيقك على جهاز شاشة كبيرة يمكن للمستخدمين فيه استخدام وضع النوافذ المتعددة. ويتوقعون أن يعمل تطبيقك بشكل جيد في ذلك البيئة.
هناك نوعان عامان من التغييرات في الحجم: التغييرات الكبيرة والتغييرات الصغيرة. التغيير الكبير في الحجم هو التغيير الذي تنطبق فيه مجموعة مختلفة من الموارد البديلة على الإعداد الجديد بسبب اختلاف في حجم الشاشة، مثل العرض أو الارتفاع أو أصغر عرض. وتشمل هذه الموارد تلك التي يحدّدها التطبيق بنفسه وتلك الواردة من أي من مكتباته.
حصر إعادة إنشاء الأنشطة بتغييرات الإعدادات المستندة إلى الحجم
عند إيقاف إعادة إنشاء Activity
بسبب تغييرات الضبط المستندة إلى الحجم، لن يعيد
النظام إنشاء Activity
. بدلاً من ذلك، يتلقّى طلبًا للاتصال بالرقم
Activity.onConfigurationChanged()
. تتلقّى أيّ مشاهدات مرفقة مكالمة إلى
View.onConfigurationChanged()
.
تكون ميزة إعادة إنشاء Activity
غير مفعّلة لتغييرات الضبط المستندة إلى الحجم عندما
يكون لديك
android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"
في ملف البيان.
السماح بإعادة إنشاء النشاط لإجراء تغييرات على الإعدادات المستندة إلى الحجم
في الإصدار 7.0 من نظام التشغيل Android (المستوى 24 من واجهة برمجة التطبيقات) والإصدارات الأحدث، Activity
لا يتم إنشاء ملف جديد إلا عند إجراء تغييرات على الإعدادات المستندة إلى الحجم إذا كان تغيير الحجم كبيرًا. عندما لا يعيد النظام
إنشاء Activity
بسبب عدم كفاية الحجم، قد يستدعي النظام
Activity.onConfigurationChanged()
و
View.onConfigurationChanged()
بدلاً من ذلك.
هناك بعض التحذيرات التي يجب مراعاتها في ما يتعلّق بطلبات Activity
وView
المُعاد الاتصال بها عندما لا تتم إعادة إنشاء Activity
:
- في الإصدارات من Android 11 (المستوى 30 لواجهة برمجة التطبيقات) حتى Android 13 (المستوى 33 لواجهة برمجة التطبيقات)، لا يتم استدعاء
Activity.onConfigurationChanged()
. - هناك مشكلة معروفة قد تؤدي إلى عدم
استدعاء
View.onConfigurationChanged()
في بعض الحالات على الإصدار Android 12L (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات المبكرة من Android 13 (المستوى 33 لواجهة برمجة التطبيقات). لمزيد من المعلومات، يُرجى الاطّلاع على هذه المشكلة العلنية. تم حلّ هذه المشكلة في الإصدارات الأحدث من Android 13 وAndroid 14.
بالنسبة إلى الرمز الذي يعتمد على الاستماع إلى التغيُّرات في الإعدادات المستندة إلى الحجم، ننصحك باستخدام أداة View
مع
View.onConfigurationChanged()
تم إلغاء تحديدها بدلاً من الاعتماد على إعادة إنشاء Activity
أو
Activity.onConfigurationChanged()
.