حالات واجهة المستخدم

الإعلانات

حفظ حالات واجهة المستخدم

حفظ \وإستعادة حالة\ حالات واجهة المستخدم، لنشاطٍ معين، في الوقت المناسب، عبر النشاط الذي يبدأه النظام..

أو تدمير التطبيق، يُعد جزءاً مهماً من تجربة المستخدم. في هذه الحالات، يتوقع المستخدم، أن تظل حالة واجهة المستخدم كما هي، لكن النظام يدمر النشاط وأي حالة مخزنة فيه.

لسد الفجوة، بين توقع المستخدم وسلوك النظام، إستخدم مزيج من كائنات ViewModel، ودالة ()onSaveInstanceState..

و/أو التخزين المحلي، لمواصلة حالة واجهة المستخدم، عبر تطبيق مماثل، وإنتقالات مثيل النشاط.

كيفية تحديد دمج هذه الخيارات، تعتمد على مدى تعقيد بيانات واجهة المستخدم، وحالات الإستخدام لتطبيقك..

والأخذ في الإعتبار سرعة التكرار، مقابل إستخدام الذاكرة.

بغض النظر عن النهج الذي تتخذه، يجب التأكد من توافق تطبيقك، مع توقعات المستخدمين بالنسبة إلى حالة واجهة المستخدم..

وتوفير واجهة مستخدم سلسة وجذابة (لتفادي التأخير في تحميل البيانات إلى واجهة المستخدم..

وخاصة بعد إجراء تغييرات التكوين بشكلٍ متكرر، مثل التدوير “تغيير إتجاه الجهاز”). في معظم الحالات، يجب عليك إستخدام كلٍ من ViewModel و ()onSaveInstanceState.

تناقش هذه الصفحة، توقعات المستخدمين حول حالة واجهة المستخدم، والخيارات المتاحة للحفاظ على الحالة، والمفاضلات والقيود لكلٍ منها.

 

 

 

توقعات المستخدم وسلوك النظام


إعتماداً على الإجراء الذي يتخذه المستخدم، فإنه يتوقع إما أن يتم مسح حالة النشاط أو المحافظة عليها.

في بعض الحالات، يقوم النظام تلقائياً بما هو متوقع، من قبل المستخدم. في حالات أخرى، يقوم النظام بعكس ما يتوقعه المستخدم.

 

 

 

رفض الشروع في حالة واجهة المستخدم من قبل المستخدم

يتوقع المستخدم أنه عندما يبدأ نشاطٍ ما، ستظل حالة واجهة المستخدم المؤقتة، لهذا النشاط كما هي، حتى يقوم المستخدم برفض النشاط بالكامل.

يمكن للمستخدم رفض النشاط بالكامل من خلال:

  • الضغط على زر العودة
  • تمرير النشاط إلى خارج شاشة النظرة العامة (التطبيقات الحديثه)
  • الإنتقال من هذا النشاط
  • إيقاف التطبيق من خلال شاشة الإعدادات
  • إكمال نوع من “إنهاء” النشاط (المدعوم بواسطة دالة “إنهاء النشاط” ()Activity.finish)

إن إفتراض المستخدم في حالات الرفض الكاملة هذه، هو بسبب أنه، قد أبتعد بشكلٍ دائم عن النشاط، وإذا أعاد فتح النشاط..

فإنه يتوقع أن يبدأ النشاط من حالة “خاليه” نظيفة. يتطابق سلوك النظام الأساسي لسيناريوهات الرفض، مع توقعات المستخدم ..

حيث سيتم تدمير مثيل النشاط وإزالته من الذاكرة، إلى جانب أي حالة مخزنة فيه وأي سجل “حالة مثيل”، تم حفظه، بشكلٍ مقترن بالنشاط.

هناك بعض الإستثناءات لهذه القاعدة، بشأن الرفض الكامل – مثال قد يتوقع المستخدم أن يأخذه المتصفح إلى..

صفحة الويب التي كان يتصفحها، قبل خروجه من المتصفح بإستخدام زر الرجوع.

 

 

 

رفض الشروع في حالة واجهة المستخدم من قبل النظام

يتوقع المستخدم أن تبقى حالة واجهة المستخدم للنشاط، كما هي خلال تغيير التكوين، مثل تدوير الشاشه، أو التبديل إلى وضع تعدد النوافذ.

ومع ذلك، بشكلٍ إفتراضي، يقوم النظام بتدمير النشاط، عند حدوث تغيير في التكوين، مما يؤدي إلى مسح أي حالة مخزنة لواجهة المستخدم في مثيل النشاط.

لمعرفة المزيد حول تكوينات الجهاز، اقرأ صفحة مرجع التكوين. لاحظ أنه من الممكن (على الرغم أنه لا يوصى به) تجاوز السلوك الإفتراضي لتغييرات التكوين.

راجع التعامل مع تتغييرات التكوين بنفسك لمزيد من التفاصيل. حفظ حالات واجهة المستخدم

يتوقع المستخدم أيضاً، بقاء حالة واجهة المستخدم لنشاطك، على حالها إذا قام بالتبديل مؤقتاً إلى تطبيق مختلف، ثم عاد إلى تطبيقك في وقتٍ لاحق.

مثال، يقوم المستخدم بإجراء بحث في نشاط البحث الخاص بك، ثم يضغط على زر الصفحة الرئيسية، أو يجيب على مكالمة هاتفية ..

عندما يعود إلى نشاط البحث، يتوقع العثور على الكلمة الرئيسية للبحث، وأن النتائج لا تزال موجودة، تماماً كما كانت من قبل.

في هذا السيناريو، يتم وضع تطبيقك في الخلفية، يبذل النظام قصارى جهده للحفاظ على عملية تطبيقك في الذاكرة.

ومع ذلك، قد يدمر النظام عملية التطبيق، بينما يتفاعل المستخدم مع التطبيقات الأخرى، بعيداً عن تطبيقك.

في مثل هذه الحالة، يتم تدمير مثيل النشاط، بالإضافة إلى أي حالة مخزنة فيه. عندما يعيد المستخدم تشغيل التطبيق..

يكون النشاط في حالة نظيفة، بشكلٍ غير متوقع. لمعرفة المزيد حول موت العملية، راجع العمليات ودورة حياة التطبيق.

 

 

 

خيارات للحفاظ على حالة واجهة المستخدم


عندما لا تتطابق توقعات المستخدم، حول حالة واجهة المستخدم، مع السلوك الإفتراضي للنظام، يجب حفظ حالة “واجهة مستخدم”..

المستخدم وإستعادتها، للتأكد من أن عملية التدمير التي يديرها النظام واضحة للمستخدم.

كل من خيارات الحفاظ على حالة واجهة المستخدم، تتباين خلال الأبعاد التالية، التي تؤثر على تجربة المستخدم:

ViewModel حالة المثيل المحفوظه التخزين المستمر
مكان التخزين في الذاكرة متسلسلة إلى القرص على القرص أو الشبكه
النجاة من تغييرات التكوين نعم نعم نعم
النجاة من عملية الموت التي يبدأها النظام لا نعم نعم
النجاة من قيام المستخدم بفصل\إنهاء ()onFinish كامل النشاط لا لا نعم
قيود البيانات الكائنات المعقده جيده، لكن المساحة محدودة بالذاكرة المتاحه فقط للأنواع البدائيه، والكائنات الصغيرة والبسيطة مثل السلسله محدودوة فقط على مساحة القرص أو تكلفة\وقت الإسترجاع من مصدر الشبكه
وقت القراءة\الكتابه سريع (الوصول للذاكرة فقط) بطيء (يتطلب تسلسل\إلغاء تسلسل و الوصول إلى القرص) بطيء (يتطلب الوصول إلى القرص أو التعامل مع الشبكه)

 

 

 

إستخدام ViewModel للتعامل مع تغييرات التكوين


يعد ViewModel مثالياً، لتخزين وإدارة البيانات، المتعلقة بواجهة المستخدم، بينما يقوم المستخدم بإستخدام التطبيق بشكلٍ نشط.

يسمح بالوصول السريع إلى بيانات واجهة المستخدم، ويساعدك على تجنب إعادة سحب البيانات، من الشبكة أو القرص خلال التدوير..

تغيير حجم النافذة، وتغييرات التكوين الأخرى الشائعة. لمعرفة كيفية تنفيذ ViewModel، راجع دليل ViewModel.

يحتفظ ViewModel بالبيانات في الذاكرة، مما يعني أنه من الأرخص إسترداد البيانات من ViewModel، بدلاً من جلبها “سحبها” من القرص أو الشبكة.

يرتبط ViewModel بنشاط (أو مالك آخر لدورة الحياة) – يبقى في الذاكرة، أثناء تغيير التكوين..

ويقوم النظام تلقائياً بربط ViewModel مع مثيل النشاط الجديد الذي ينتج بسبب تغيير التكوين.

يتم تدمير ViewModels تلقائياً، بواسطة النظام، عندما يقوم المستخدم بالتراجع عن نشاطك، أو شظيتك، أو إذا كنت تستدعي دالة الإنهاء ()finish..

مما يعني أنه سيتم مسح الحالة، كما يتوقع المستخدم في هذه السيناريوهات.

بخلاف حالة المثيل المحفوظة، يتم تدمير ViewModels أثناء عملية الإيقاف، التي أطلقها النظام.

لهذا السبب يجب عليك إستخدام كائنات ViewModel، مع ()onSaveInstanceState (أو بعض من أقراص التخزين الأخرى “مثل الهاردسك”)..

إخفاء معرّفات في saveInstanceState، للمساعدة في عرض النماذج، التي تعيد تحميل البيانات بعد إيقاف النظام.

إذا كان لديك بالفعل، حل في الذاكرة، لتخزين حالة واجهة مستخدمك، عبر تغييرات التكوين، فقد لا تحتاج إلى إستخدام ViewModel.

 

 

 

 

 

 

إستخدام ()onSaveInstanceState كنسخة إحتياطية للتعامل مع عملية الإيقاف التي أطلقها النظام


يقوم الإستدعاء ()onSaveInstanceState بتخزين البيانات اللازمة، لإعادة تحميل، حالة وحدة تحكم واجهة المستخدم، مثل النشاط أو الشظيه..

في حالة قيام النظام، بتدمير وحدة التحكم، ثم إعادة تكوينها لاحقاً. لمعرفة كيفية تنفيذ حالة مثيل محفوظة، اقرأ حفظ وإستعادة حالة النشاط في دليل دورة حياة النشاط.

حزم حالة المثيل المحفوظة، تستمر في كلٍ من تغييرات التكوين، وموت “إيقاف” العملية، ولكنها محدودة بمقدار التخزين والسرعة لأن..

()onSavedInstanceState تقوم بنشر البيانات بشكلٍ متسلسل إلى القرص. التسلسل يمكن أن يستهلك الكثير من الذاكرة..

إذا كانت الكائنات التي يتم نشرها بتسلسل معقدة. لأن هذه العملية، تحدث على مؤشر الترابط الرئيسي، أثناء تغيير التكوين..

فإن التسلسل يمكن أن يتسبب في إسقاط الإطارات، والتردد البصري، إذا أستغرق وقتاً طويلاً جداً.

لا تستخدم التخزين ()onSavedInstanceState، لتخزين كميات كبيرة من البيانات، مثل الصور النقطية، أو بنية البيانات المعقدة..

التي تتطلب تسلسل مطول أو إلغاء تسلسل. بدلاً من ذلك، قم بتخزين الأنواع البدائية والبسيطة، والكائنات الصغيرة مثل السلسلة.

وعلى هذا النحو، إستخدم ()onSaveInstanceState لتخزين قدر ضئيل، من البيانات الضروريه، مثل المعرف، لإعادة إنشاء البيانات الضرورية..

لإستعادة واجهة المستخدم مرة أخرى، إلى حالتها السابقة، في حالة فشل آليات التخزين الأخرى.

يجب أن تقوم معظم التطبيقات بتنفيذ ()onSaveInstanceState للتعامل مع عملية الإيقاف التي يطلقها النظام.

بناءً على حالات إستخدام تطبيقك، قد لا تحتاج إلى إستخدام ()onSaveInstanceState على الإطلاق.

على سبيل المثال، قد يقوم المتصفح بإعادة المستخدم إلى صفحة الويب، التي كان يتصفحها قبل الخروج من المتصفح.

إذا كان نشاطك يتصرف بهذه الطريقة، فيمكنك الإستغناء عن إستخدام ()onSaveInstanceState وبدلاً من ذلك قم بتخزين كل شيء محلياً.

بالإضافة إلى ذلك، عندما تقوم بفتح نشاط من خلال غرض، يتم تسليم مجموعة الإضافات إلى النشاط عندما يتغير التكوين، وعندما يستعيد النظام النشاط.

لو أن جزء من بيانات حالة واجهة المستخدم، مثل إستعلام البحث، تم تمريره كغرض إضافي عند إطلاق النشاط..

فيمكنك إستخدام حزمة الإضافات، بدلاً من حزمة ()onSaveInstanceState. لمعرفة المزيد حول الإضافات الغرض، راجع الغرض ومرشحات الغرض.

في أي من هذه السيناريوهات، يجب عليك إستخدام ViewModel لتجنب إهدار دورات إعادة تحميل البيانات، من قاعدة البيانات أثناء تغيير التكوين.

في الحالات التي تكون فيها، بيانات واجهة المستخدم المطلوب الحفاظ عليها، بسيطة وخفيفة، قد تستخدم ()onSaveInstanceState بمفردها للإحتفاظ ببيانات الحاله.

 

 

 

 

 

إستخدام التخزين المحلي للتعامل مع عملية موت البيانات المعقدة أو الكبيرة


التخزين المحلي المستمر، مثل قاعدة البيانات أو التفضيلات المشتركة، سوف يظل قائماً طالما ظل تطبيقك مثبتاً على جهاز المستخدم..

(ما لم يمسح المستخدم بيانات تطبيقك). في حين أن هذا التخزين المحلي، يبقي على النشاط الذي أطلقه النظام، وموت عملية التطبيق..

يمكن أن يكون إسترداده مكلفاً، نظراً لأنه يجب قراءته من التخزين المحلي بالذاكرة. غالباً ما تكون هذه السعة التخزينية الدائمة..

جزءاً من بنية تطبيقك، لتخزين جميع البيانات، التي لا تريد أن تفقدها، إذا فتحت وأغلقت النشاط.

لا مثيل ViewModel ولا حالة المثيل المحفوظة، تمثلان حلول تخزين طويلة الأجل، وبالتالي ليست بدائل للتخزين المحلي، مثل قاعدة البيانات.

بدلاً من ذلك، يجب عليك إستخدام هذه الآليات، للتخزين المؤقت، لحالة واجهة المستخدم المؤقتة فقط، وإستخدام التخزين الدائم لبيانات التطبيق الأخرى.

راجع دليل بنية التطبيق للحصول على مزيد من التفاصيل، حول كيفية الإستفادة من التخزين المحلي..

للحفاظ على بيانات تطبيقك على المدى الطويل (مثال، خلال إعادة تشغيل الجهاز).حفظ حالات واجهة المستخدم

 

 

 

 

إدارة حالة واجهة المستخدم: فرق تسد


يمكنك حفظ وإستعادة حالة واجهة المستخدم بفعالية، بتقسيم العمل بين مختلف أنواع آليات التخزين المستمر.

في معظم الحالات، يجب أن تقوم كلٍ من هذه الآليات، بتخزين نوع مختلف من البيانات المستخدمة في النشاط..

بناءً على مفاضلات تعقيد البيانات، سرعة الوصول، والعمر:

– التخزين المحلي المستمر: يخزن جميع البيانات، التي لا تريد أن تفقدها، إذا فتحت وأغلقت النشاط.

  • مثال: مجموعة من كائنات الأغاني، والتي قد تتضمن ملفات صوتية وبيانات وصفية.

 

ViewModel: تخزن في الذاكرة جميع البيانات، اللازمة لعرض وحدة التحكم، المقترنة بواجهة المستخدم.

  • مثال: كائنات الأغنية في عمليات البحث الحديثه وأحدث إستعلام بحث.

 

 

()onSaveInstanceState : تخزن كمية صغيرة من البيانات، اللازمة لإعادة تحميل حالة النشاط بسهولة..

إذا توقف النظام، ثم قام بإعادة إنشاء وحدة تحكم واجهة المستخدم. بدلاً من تخزين الكائنات المعقدة هنا..

قم بتخزين الكائنات المعقدة بإستمرار في التخزين المحلي، وقم بتخزين معرف فريد لهذه الكائنات في ()onSaveInstanceState.

  • مثال: تخزين أحدث إستعلام للبحث.

 

مثال، ضع في الإعتبار، نشاط يسمح لك بالبحث في مكتبة الأغاني الخاصة بك. في ما يلي كيفية التعامل مع الأحداث المختلفة:

عندما يضيف المستخدم أغنية، يقوم ViewModel على الفور، بتفويض هذه البيانات محلياً. إذا كانت هذه الأغنية المضافة حديثاً..

هي شيء يجب إظهاره في واجهة المستخدم، فيجب عليك أيضاً تحديث البيانات في كائن ViewModel ليعكس إضافة الأغنية.

تذكر أن تقوم بجميع إدخالات قاعدة البيانات، خارج مؤشر الترابط الرئيسي.

عندما يبحث المستخدم عن أغنية، أياً كانت بيانات الأغنية المعقدة، التي تقوم بتحميلها من قاعدة البيانات..

إلى وحدة تحكم واجهة المستخدم، يجب تخزينها على الفور في كائن ViewModel. يجب عليك أيضاً حفظ إستعلام البحث نفسه في كائن ViewModel.

عندما ينتقل النشاط إلى الخلفية، يقوم النظام بإستدعاء ()onSaveInstanceState. يجب عليك حفظ إستعلام البحث في حزمة ()onSaveInstanceState .

هذه الكمية الصغيرة من البيانات، سهلة الحفظ. وهي أيضاً كل المعلومات التي تحتاجها لإعادة النشاط إلى حالته الحالية.

 

 

 

 

 

إستعادة الحالات المعقدة: إعادة تجميع القطع


عندما يحين وقت عودة المستخدم إلى النشاط، سيكون هناك سيناريوهين محتملان لإعادة إنشاء النشاط:

  • يتم إعادة إنشاء النشاط، بعد أن تم إيقافه بواسطة النظام. حفظ حالات واجهة المستخدم حفظ حالات واجهة المستخدم

يحتوي النشاط على الإستعلام المحفوظ، في حزمة ()onSaveInstanceState ، ويجب أن يقوم بتمرير الإستعلام إلى ViewModel.

ترى ViewModel أنه لا يحتوي على نتائج بحث مخزنة مؤقتاً، وأن المفوضين يقومون بتحميل نتائج البحث، بإستخدام إستعلام البحث المحدد.

 

 

  • يتم إنشاء النشاط بعد تغيير التكوين. حفظ حالات واجهة المستخدم حفظ حالات واجهة المستخدم

يحتوي النشاط على إستعلام البحث المحفوظ، في حزمة ()onSaveInstanceState ، وقد قامت ViewModel بالفعل بتخزين نتائج البحث مؤقتاً.

يمكنك تمرير الإستعلام من الحزمة ()onSaveInstanceState إلى ViewModel، والتي تحدد أنه قام بالفعل بتحميل البيانات الضرورية..

وأنه لا يحتاج إلى إعادة الإستعلام عن قاعدة البيانات.

ملاحظة: عندما يتم إنشاء نشاط في البداية، فإن الحزمة ()onSaveInstanceState لا تحتوي على بيانات، ويكون كائن ViewModel فارغاً.

عند إنشائك كائن ViewModel، قم بتمرير إستعلام فارغ، والذي يخبر كائن ViewModel أنه لا توجد بيانات للتحميل حتى الآن. لذلك، يبدأ النشاط في الحالة الفارغة.

 


للإطلاع على المقال باللغة الإنجليزية أضغط هنا.

الإعلانات