واحدة من الأشياء الجيدة التي وفرتها جوجل لعالم الأندرويد هو Architecture Components والتى أتى من بعدها Android Jetpack. لقد جعل كل هذا حياة المبرمجين أكثر تنظيمًا وقابلية للتجريب.
بالتأكيد - كمطوري أندرويد - قد رأينا أننا يجب أن نقوم بتنفيذ منظومة أوامر معينة فى حدث محدد (Lifecycle Event) مثل (onResume, onCreate)، على سبيل المثال ؛ تسجيل (Callbacks) فى (onResume) وإلغاء تسجيلهم فى (onPause) لأنك لو لسبب ما لم تقم بإلغاءهم قد تتعرض لمشاكل بالذاكرة او قد يتوقف التطبيق بسبب (Runtime Crashes). بالإضافة، إلى أن نظام الاوامر لديك قد يصبح أبشع مع الوقت عندما تضطر لعمل أى مهام منطقية فى حدث ما.
ماذا عن الـ (Context References) - سواء كان Application او Activity - التى قد تستخدمها فى (Class) أخرى لسبب ما، عليك أن توفر طريقة للتخلص من الـ(Context Reference) حتى يتمكن الـ(Garbage Collector) من تجميعه وذلك كله لتجنب مشاكل الذاكرة، ومن هنا قد ينتهى بك الأمر لعمل العديد من الأشياء فى فى حدث واحد ، ستصبح المنظومة أبشع، ومن هنا يأتى دور (Lifecycle Component) لحل المشكلة.
يوفر لنا Lifecycle component طريقة سهلة لتجعل عقلك و منظومة الأوامر أكثر تنظيمًا، نبدأ بمثال بسيط:
class SimpleInteraction(private var listener: InteractionCallback? = null) {
private var TAG = "SimpleInteraction"
private var isListening = false
private fun unregisterCallback() {
listener = null
}
fun startListening() {
isListening = true
}
fun stopListening() {
isListening = false
unregisterCallback()
}
fun doingSomeAction() {
Log.d(TAG, "Action happened, call the interaction callback")
if (isListening) {
listener?.onInteraction()
}
}
interface InteractionCallback {
fun onInteraction()
}
}
فى هذا المثال، نستخدم هذه الـ Class لاستدعاء Listener Interface للتفاعل مع حدث ما، حسنًا، لنفترض أن هذا Callback يتم تنفيذه بواسطة Activity، أولاً ستحتاج إلى إنشاء SimpleInteraction class في activity وتمرير (this) نظرًا لأنها InteractionCallback ثم في onResume() تحتاج إلى إستدعاء startListening() وفي onPause() ستستدعى stopListening()،حسناُ، يبدو وكأنه عديد من الأشياء فقط لاستخدام هذه Class.
يجعل استخدام Lifecycle Arch Component حياتك أسهل كثيرًا والأمور التي تدخلها أكثر تنظيماً. حسنا دعنا نرى كيف نستخدمها.
أولًا، تحتاج إلى إضافة dependency في build.gradle(app) ومزامنة مشروعك:
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
and if you’re not using AndroidX include this dependency instead
def lifecycle_version = "1.1.1"
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
إذا كنت لا تستخدم AndroidX، فعليك إدراجdependency التالية:
def lifecycle_version = "1.1.1"
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
ثم اجعل SimpleInteraction class تستخدم LifecycleObserver.
هنا الجزء الجيد، function التي تريد استدعاء في onResume () قم بتمييزها باستخدام annotation:
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
و function التى تريد استدعائها في onPause() قم بتمييزها ب:
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
وهذا كل شيء، والآن يمكنك أن تضمن أن تلك functions سيتم استدعاؤها في تلك events. هناك شيء واحد فقط ما زال متبقيًا، أضف LifecycleObserver إلى LifecycleOwner (على سبيل المثال Activity):
activity.lifecycle.addObserver(simpleInteractionObject)
في المقال الخاص بنا، قمنا بتمرير lifecycle owner إلى class لجعل الأمور أكثر بساطة وتنظيمًا:
class SimpleInteraction(lifecycleOwner: LifecycleOwner, private var listener: InteractionCallback? = null) : LifecycleObserver {
init {
lifecycleOwner.lifecycle.addObserver(this)
}
private var TAG = "SimpleInteraction"
private var isListening = false
private fun unregisterCallback() {
listener = null
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun startListening() {
isListening = true
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun stopListening() {
isListening = false
unregisterCallback()
}
fun doingSomeAction() {
Log.d(TAG, "Action happened, call the interaction callback")
if (isListening) {
listener?.onInteraction()
}
}
interface InteractionCallback {
fun onInteraction()
}
}
LifecycleOwner هو واجهة يتم تنفيذها بواسطة class الذي يمتلك أو يحتفظ به أويعمل خلال lifecycle محددة، مثل الأنشطة و الأجزاء. ينفذون هذه الواجهة لنشر حالتهم ل observer مثل حالنا في المثال أعلاه.
يمكنك إنشاء LifecycleOwner class خاص بك، لنأخذ مثالاً، دعنا نقول أنك لا تحب نظام التنقل الخاص بالأندرويد وقررت استخدام نظام تنقل آخر لتلبية احتياجاتك، دعنا نقول أنك اخترت:
Conductor Framework يمكنك التحقق من ذلك على هذا الرابط أو حتى ترغب في إنشاء نظام التنقل الخاص بك.
لديك Controller class والتى تتحكم في العرض تمامًا مثل Fragment، والتي لديها lifecycle خاص بها. في هذه الحالة، كيف يمكنك جعل SimpleInteraction Class الخاصة بك تستمع إلى controller lifecycle، مع العلم أن Controller لا تقوم بتطبيق Lifecycle واجهة المستخدم بشكل افتراضي.
لنشر events الخاصة ب Controller بحيث يمكنك تسجيل observer الخاص بك للاستماع إليها، تحتاج إلى تنفيذ واجهة LifecycleOwner في Controller الخاصة بك.
class ChatController(args: Bundle) : Controller(args), LifecycleOwner
ثم يجب عليك إنشاء LifecycleRegistery object في controller الخاصة بك:
mLifecycleRegistry = LifecycleRegistry(this)
ثم عليك تنفيذ interface function:
getLifecycle()
ثم إعادة LifecycleRegistery:
override fun getLifecycle(): Lifecycle {
return mLifecycleRegistry
}
كل ما عليك القيام به هو نشر controller's lifecycle events الخاصة بك تمامًا مثل:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
mLifecycleRegistry = LifecycleRegistry(this)
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
وكذلك ل lifecycle events آخرى، وهذا كل ما في الأمر لقد جعلت Controller a LifecycleOwner ويمكنك مراقبة هذه events في أي class.