مثال مبسط على ViewModel & LiveData في Android

بسم الله الرحمن الرحيم

مؤخرا, في google IO 17 تم الإعلان عن New Architecture Component وفي هذه المقالة سنتحدث عن اثنين منهم وهما ViewModel & LiveData.

بداية لنفرض أن لدينا تطبيق بهذا الشكل

عند الضغط على button Add one سيتم إضافة 1 للقيمة الموجودة في textView, وسيكون كود layout  كالتالي

أما Activity كالتالي

الكود بسيط جدا, ويعمل بطريقة صحيحة, ولكن حينما تقوم بتغيير وضع الشاشة إلى landscape بدل portrait ستعود قيمة textView إلى 0, لأن Activity قد حصل لها destroy ثم create من جديد, سابقا يتم حل مثل هذه المشاكل التي يكون لها علاقة ب configChanges عن طريق استخدام onSaveInstanceState و  onRestoreInstanceState, جميل جدا, سنتحدث عن أحد الحلول الجديدة لهذه المشكلة وهو ViewModel.

ViewModel:

هو class تم تصمميه لتعامل مع data الخاصة ب view, والميزة المضافة أنه يخزن البيانات في حالة configChanges, جميل جدا, لنبدأ بعمل refactor للكود السابق بإنشاء Model يقوم بعمل extends ل ViewModel

جميل جدا الان سنقوم باستخدام هذا class في MainActivity كـ Composition Object ثم نقوم بإنشائه في onCreate, ليصبح شكل Activity كالتالي:

نلاحظ أننا نستخدم في الإنشاء ViewModelProviders, وهي ستقوم بحفظ وتخزين ViewModel ل activity  المعطى, بمعنى, في حال حدثت حالة configChanges -كتغير orientation- ل activity سيقوم  class ViewModelProviders بتخزين بيانات ViewModel ولذلك نقوم بإعطائه هذا المعلومات أثناء التعريف

الان في حال قمنا بعمل rotation لن تتأثر البيانات حيث تم الإحتفاظ بها عن طريق ViewModelProviders

جميل جدا, لنضيف ال component الأخرى للكود الخاص بنا.

LiveData:

LiveData تتيح ل lifeCycleOwner -سواء كان Activity or Fragment- أنه يستقبل الداتا من ViewModel عن طريق ال مراقبة -observing- أي تعديل يطرأ على ViewModel class, جميل جدا, إذا بدلا من أن نقوم بتحديث UI في كل مرة بإستخدام setters و getters, سنقوم بإسلوب جديد سنستعرضه في المثال التالي
أولا لنقوم بعمل refactor ل viewModel الخاص بناء ليصبح كالتالي

قمنا بتغيير نوع البيانات الذي نتعامل معه إلى MutableLiveData<Object> وتعديل set & get, جميل جدا لننتقل إلى Main

قمت comment قبل كل سطر تم حذفه ليسهل عليك مشاهدة التعديل, بداية قمنا بعمل Observer<Object> لديه دالة واحدة فقط وهي onChanged, يتم استدعاؤها إذا حصل أي تعديل للبيانات, بعد ذلك قمنا بعمل Observe عن طريق هذا السطر في onCreate

كما تلاحظ لدينا Observer سيستدعي دالة onChanged في كل مرة يتم تعديل البيانات, بشرط أن يكون State ل lifeCycleOwner في STARTED أو RESUMED, ويكون LifecycleOwner في حالة STARTED في حالتين الأولى بعد استدعاء دالة onStart, الثانية, قبل استدعاء دالة onPause, ويكون LifecycleOwner في حالة RESUMED بعد استدعاء دالة onResume.
ولذلك عندما قمنا بعمل Observe أعطينا الدالة Observer, بالإضافة إلى LifecycleOwner الذي هو مرتبط به.

ينبغي الإشارة إلى نقطة في غاية الأهمية, في حال كان التطبيق يعمل لكنه في  Background وتعرض النظام لما نسميه Low Memory, سيقوم النظام بإعادة استخدام resources بالتخلص -kill-  من التطبيقات الموجودة في Background, وفي حال كنت تعتمد فقط على ViewModel ببساطة ستفقد بياناتك, على عكس onSaveInstanceState التي كانت تحل هذه المشكلة.

إلى هنا أتمنى أن أكون وفقت في تبسيط المفهوم, ولاشك أنك ستحتاج لمزيد من القراءة لتعامل مع بيانات أعقد من المذكورة في المثال.

والسلام عليكم ورحمة الله وبركاته.

المصادر

Android Architecture Components by Example

Android Architecture Components

ViewModels : A Simple Example

اترك تعليقاً