دورات حياة النشاط

الإعلانات

فهم دورات حياة النشاط

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

توفر فئة النشاط عدداً من، عمليات الإستدعاء، التي تسمح للنشاط بمعرفة تغير الحالة: أي أن النظام يقوم..

بإنشاء، أو إيقاف، أو إستئناف النشاط، أو تدمير العملية، التي يتواجد فيها النشاط.

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

مثال، إذا كنت بصدد إنشاء مشغل فيديو، فيمكنك إيقاف الفيديو مؤقتاً، وإنهاء الإتصال بالشبكة عندما ينتقل المستخدم إلى تطبيق آخر.

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

بمعنى آخر، يتيح لك كل إستدعاء، إجراء عمل محدد، يناسب تغيير معين للحالة.

القيام بالعمل المناسب، في الوقت المناسب، والتعامل مع التحولات بشكلٍ صحيح، يجعل تطبيقك أكثر قوة وأداءً.

مثال، قد يساعدك التنفيذ الجيد، لدورة حياة الإستدعاءات، على ضمان تجنب تطبيقك:

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

– إستهلاك موارد النظام القيّمة، عندما لا يستخدمها المستخدم بشكلٍ نشط.

– فقدان تقدم المستخدم، إذا غادر تطبيقك وعاد إليه في وقتٍ لاحق.

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

 

هذه الوثيقة تشرح دورة حياة النشاط بالتفصيل. تبدأ الوثيقة بوصف نموذج دورة الحياة. بعد ذلك، تشرح عمليات الإستدعاء كلٍ من:

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

وأخيراً، تناقش العديد من الموضوعات، المتعلقة بالإنتقال بين حالات النشاط.

للحصول على معلومات حول التعامل مع دورات الحياة، بما في ذلك إرشادات حول أفضل الممارسات..

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

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

 

 

 

 

 

فهم دورات حياة النشاط

 

مفاهيم دورة حياة النشاط


للتنقل بين مراحل دورة حياة النشاط، توفر فئة النشاط مجموعة أساسية من ستة عمليات إستدعاء:

()onCreate و ()onStart و ()onResume  و ()onPause  و ()onStop  و ()onDestroy. يستدعي النظام كلٍ من، عمليات الإستدعاء هذه، كلما دخل النشاط في حالة جديدة.

 

يقدم الشكل 1 تمثيلاً مرئياً لهذا النموذج.

عندما يبدأ المستخدم في مغادرة النشاط، يقوم النظام بإستدعاء دوال لتفكيك النشاط.

في بعض الحالات، يكون هذا التفكيك جزئياً فقط؛ ولا يزال النشاط موجوداً في الذاكرة (مثل عندما ينتقل المستخدم إلى تطبيق آخر)..

ولا يزال بإمكانه العودة إلى المقدمة.

إذا عاد المستخدم إلى هذا النشاط، فسوف يستأنف النشاط من حيث توقف المستخدم.

ومن المحتمل قيام النظام بقتل عملية معينة – بالإضافة إلى الأنشطة الموجودة فيها –

إعتماداً على حالة النشاط في ذلك الوقت.

 

الشكل 1. شكل مبسط من دورة حياة النشاط.

 

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

إعتماداً على مدى تعقيد نشاطك، قد لا تحتاج إلى تنفيذ جميع جوال دورة الحياة.

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

يقدم القسم التالي من هذا المستند، تفاصيل حول عمليات الإستدعاء، التي تستخدمها للتعامل مع عمليات التنقل بين الحالات.

 

 

 

 

 

فهم دورات حياة النشاط

 

إستدعاءات دورة الحياة


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

بعض الإجراءات، مثل إستدعاء ()setContentView ، تنتمي إلى دوال دورة حياة النشاط نفسها.

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

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

 

 

()OnCreate

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

في دالة “بدء الإشاء” ()onCreate ، يمكنك تنفيذ، منطق بدء التشغيل الأساسي، الذي يجب أن يحدث مرة واحدة فقط طوال مدة النشاط.

مثال، قد يؤدي تنفيذ ()onCreate إلى ربط البيانات بالقوائم، وإقران النشاط بـ ViewModel ، وإنشاء بعض متغيرات مجال الفئه.

تستلم هذه الدالة المعامل “باراميتر” saveInstanceState ، وهو عبارة عن كائن حزمة، يحتوي على حفظ حالة النشاط السابقة.

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

إذا كان لديك مكون مدرك لدورة الحياة، ومقيد بدورة حياة نشاطك، فسوف يتلقى الحدث ON_CREATE.

سيتم إستدعاء الداله التي تم شرحها بإستخدام OnLifecycleEvent@ بحيث يمكن للمكون المدرك لدورة الحياة، تنفيذ أي كود إعداد يحتاجه، للحالة التي تم إنشاؤها.

يوضح المثال التالي لدالة ()onCreate الإعداد الأساسي للنشاط، مثل إعلان واجهة المستخدم (المعرفة في ملف المخطط XML)..

وتعريف المتغيرات الخاصة بالأعضاء، وتهيئة بعض من واجهة المستخدم. في هذا المثال، يتم تحديد ملف مخطط XML..

بتمرير معرف مصدر الملف R.layout.main_activity لـ ()setContentView .

KOTLIN

lateinit var textView: TextView

// some transient state for the activity instance
var gameState: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
    // call the super class onCreate to complete the creation of activity like
    // the view hierarchy
    super.onCreate(savedInstanceState)

    // recovering the instance state
    gameState = savedInstanceState?.getString(GAME_STATE_KEY)

    // set the user interface layout for this activity
    // the layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.activity_main)

    // initialize member TextView so we can manipulate it later
    textView = findViewById(R.id.text_view)
}

// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY)
}

// invoked when the activity may be temporarily destroyed, save the instance state here
override fun onSaveInstanceState(outState: Bundle?) {
    outState?.run {
        putString(GAME_STATE_KEY, gameState)
        putString(TEXT_VIEW_KEY, textView.text.toString())
    }
    // call superclass to save any view hierarchy
    super.onSaveInstanceState(outState)
}

JAVA

TextView mTextView;

// some transient state for the activity instance
String mGameState;

@Override
public void onCreate(Bundle savedInstanceState) {
    // call the super class onCreate to complete the creation of activity like
    // the view hierarchy
    super.onCreate(savedInstanceState);

    // recovering the instance state
    if (savedInstanceState != null) {
        mGameState = savedInstanceState.getString(GAME_STATE_KEY);
    }

    // set the user interface layout for this activity
    // the layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity);

    // initialize member TextView so we can manipulate it later
    mTextView = (TextView) findViewById(R.id.text_view);
}

// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    mTextView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}

// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putString(GAME_STATE_KEY, mGameState);
    outState.putString(TEXT_VIEW_KEY, mTextView.getText());

    // call superclass to save any view hierarchy
    super.onSaveInstanceState(outState);
}

 

كبديل لتعريف ملف XML وتمريره إلى ()setContentView ، يمكنك إنشاء كائنات معاينه جديدة في كود نشاطك..

وبناء تسلسل هرمي للمعاينه عن طريق إدراج طرق معاينه جديدة في ViewGroup. ثم إستخدام هذا المخطط..

عن طريق تمرير “مجموعة ViewGroup الأصليه” إلى ()setContentView . لمزيد من المعلومات حول إنشاء واجهة مستخدم، اقرأ وثائق واجهة المستخدم.

نشاطك لا يتواجد في حالة الإنشاء. بعد إنتهاء تنفيذ الدالة ()onCreate، يدخل النشاط في حالة البدء..

ويستدعي النظام دالتي ()onStart و ()onResume بتتابع سريع. المقطع التالي يشرح إستدعاء ()onStart.

 

 

()onStart

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

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

عندما ينتقل النشاط إلى حالة البدء، أي مكون مدرك لدورة الحياة، ومرتبط بدورة حياة النشاط سوف يتلقى الحدث ON_START.

تكتمل الدالة ()onStart بسرعة كبيرة، كما هو الحال مع حالة الإنشاء، لا يبقى النشاط متواجداً في حالة البدء.

بمجرد إنتهاء هذا الإستدعاء، يدخل النشاط في الحالة المستأنفة، ويستدعي النظام دالة ()onResume .

 

 

()onResume

عندما يدخل النشاط في حالة الإستئناف، فإنه يأتي إلى المقدمة، ثم يقوم النظام بإستدعاء ()onResume .

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

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

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

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

عند حدوث حدث “مقاطعة”، يدخل النشاط في حالة الإيقاف المؤقت، ويستدعي النظام ()onPause.

إذا عاد النشاط إلى حالة الإستئناف من حالة الإيقاف المؤقت، يقوم النظام مرة أخرى بإستدعاء دالة ()onResume .

لهذا السبب، يجب عليك تنفيذ ()onResume لتهيئة المكونات التي قمت بتحريرها أثناء “الإيقاف المؤقت” ()onPause ..

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

في ما يلي مثال لمكون مدرك لدورة الحياة، يصل إلى الكاميرا، عندما يتلقى المكوّن حدث ON_RESUME:

KOTLIN

class CameraComponent : LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun initializeCamera() {
        if (camera == null) {
            getCamera()
        }
    }

    ...
}

JAVA

public class CameraComponent implements LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void initializeCamera() {
        if (camera == null) {
            getCamera();
        }
    }

    ...
}

 

 

 

يعمل الكود أعلاه على تهيئة الكاميرا بمجرد إستلام LifecycleObserver لحدث ON_RESUME. مع ذلك، في وضع تعدد النوافذ..

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

وينقر على النافذة الأخرى التي لا تحتوي على نشاطك، سينتقل نشاطك إلى حالة الإيقاف المؤقت.

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

إذا كنت تريد إبقاء الكاميرا نشطة بينما يكون النشاط متوقف مؤقتاً ولكنه مرئي (على سبيل المثال في وضع تعدد النوافذ)..

فيجب عليك بدلاً من ذلك تهيئة الكاميرا بعد حدث ON_START. مع ذلك، لاحظ أن بقاء الكاميرا نشطة، أثناء إيقاف نشاطك مؤقتاً..

قد يمنع وصول الكاميرا إلى تطبيق آخر مستأنف في وضع تعدد النوافذ. قد يكون من الضروري في بعض الأحيان الحفاظ على نشاط الكاميرا..

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

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

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

إذا قمت بتهيئة شيء ما بعد حدث ON_START، فقم بتحريره أو إنهائه بعد حدث ON_STOP. إذا قمت بالتهيئة بعد حدث ON_RESUME ، فقم بتحريره بعد الحدث ON_PAUSE.

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

إستدعاء دورة النشاط مثل ()onStart و ()onStop ولكن هذا غير مستحسن. تسمح لك إضافة هذا المنطق إلى..

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

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

 

 

 

 

 

فهم دورات حياة النشاط

 

()onPause

يقوم النظام بإستدعاء هذه الدالة بإعتبارها أول مؤشر على أن المستخدم يغادر نشاطك (على الرغم من أن هذا لا يعني دائماً أن النشاط قد تم تدميره)؛..

يشير إلى أن النشاط لم يعد في المقدمة (على الرغم من أنه قد يكون مرئياً إذا كان المستخدم في وضع تعدد النوافذ).

إستخدم دالة ()onPause لإيقاف أو ضبط العمليات التي يجب ألا تستمر (أو يجب أن تستمر في الإعتدال) أثناء وجود النشاط في حالة الإيقاف المؤقت..

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

– تقوم بعض الأحداث بمقاطعة تنفيذ التطبيق، كما هو موضح في قسم ()onResume. هذه هي الحالة الأكثر شيوعاً.

– في أندرويد 7.0 (مستوى واجهة برمجة التطبيقات 24) أو أعلى، يتم تشغيل العديد من التطبيقات في وضع تعدد النوافذ.

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

– يتم فتح نشاط جديد شبه شفاف (مثل مربع حوار). طالما أن النشاط لا يزال مرئياً جزئياً ولكنه ليس في وضع التركيز، فإنه يظل متوقف مؤقتاً.

عندما ينتقل النشاط إلى حالة التوقف المؤقت، فأن أي مكون مدرك لدورة الحياة مرتبط بدورة حياة النشاط سوف يتلقى الحدث ON_PAUSE.

هذا هو المكان حيث يمكن لمكونات دورة الحياة، إيقاف أي وظيفة لا تحتاج إلى تشغيل أثناء عدم وجود المكون في المقدمة، مثل إيقاف معاينة الكاميرا.

يمكنك أيضاً إستخدام دالة ()onPause لتحرير موارد النظام، التعامل مع المستشعرات (مثل مستشعر GPS)، أو أي موارد قد تؤثر على..

عمر البطارية بينما يتم إيقاف نشاطك مؤقتاً، ولا يحتاج المستخدم إليه. مع ذلك، وكما ذكر أعلاه في قسم ()onResume ..

قد يبقى النشاط المتوقف مؤقتاً مرئياً بالكامل، إذا كان في وضع تعدد النوافذ. و على هذا النحو، يجب عليك التفكير في..

إستخدام ()onStop بدلاً من ()onPause لتحرير أو تعديل الموارد والعمليات المتعلقة بشكلٍ كامل بواجهة المستخدم لدعم وضع تعدد النوافذ بشكلٍ أفضل.

المثال التالي لتفاعل LifecycleObserver مع حدث ON_PAUSE هو النظير لمثال الحدث ON_RESUME أعلاه..

حيث تم إطلاق الكاميرا التي تمت تهيئتها بعد إستلام الحدث ON_RESUME:

KOTLIN

class CameraComponent : LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun releaseCamera() {
        camera?.release()
        camera = null
    }

    ...
}

JAVA

public class JavaCameraComponent implements LifecycleObserver {

    ...

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void releaseCamera() {
        if (camera != null) {
            camera.release();
            camera = null;
        }
    }

    ...
}

 

لاحظ أن مقتطف الكود أعلاه يضع كود إطلاق الكاميرا بعد إستلام حدث ON_PAUSE بواسطة LifecycleObserver.

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

 

تنفيذ ()onPause مختصراً جداً، ولا يُعطي بالضرورة وقتاً كافياً لتنفيذ عمليات الحفظ. لهذا السبب، يجب ألا تستخدم ()onPause لحفظ بيانات التطبيق..

أو المستخدم أو إجراء إتصال بالشبكة أو تنفيذ عمليات قاعدة البيانات؛ عمل مماثل قد لا يكتمل قبل إكتمال الدالة.

بدلاً من ذلك، يجب إجراء عمليات إيقاف تشغيل الحمل الكثيف أثناء ()onStop . لمزيد من المعلومات حول العمليات المناسبة للأداء أثناء ()onStop ، راجع ()onStop .

لمزيد من المعلومات حول حفظ البيانات، اقرأ حفظ وإستعادة حالة النشاط.

إكمال دالة ()onPause لا يعني أن النشاط يترك الحالة متوقفة مؤقتاً. بدلاً من ذلك، يظل النشاط في هذه الحالة حتى يُستأنف النشاط..

أو يصبح غير مرئي تماماً للمستخدم. إذا تم إستئناف النشاط، سوف يقوم النظام مرة أخرى بإستدعاء ()onResume .

إذا عاد النشاط من حالة الإيقاف المؤقت إلى حالة الإستئناف، يحتفظ النظام بمثيل النشاط المقيم في الذاكرة..

يعيد إستدعاء ذلك المثيل عندما يستدعي النظام ()onResume . في هذا السيناريو، لا تحتاج إلى إعادة تهيئة المكونات التي تم إنشاؤها..

أثناء أي من دوال الإستدعاء السابقة للحالة التي تم إستئنافها. إذا أصبح النشاط غير مرئي تماماً، يقوم النظام بإستدعاء ()onStop . يناقش المقطع التالي الإستدعاء ()onStop .

 

 

 

 

 

فهم دورات حياة النشاط

 

()onStop

عندما لا يعود نشاطك مرئياً للمستخدم، فقد دخل إلى حالة الإيقاف، ويقوم النظام بإستدعاء ()onStop.

قد يحدث هذا ، كمثال، عندما يغطي نشاط تم إطلاقه حديثاً الشاشة بأكملها. قد يقوم النظام أيضاً بإستدعاء ()onStop عند إنتهاء تشغيل النشاط، ويوشك على الإنهاء.

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

هذا هو المكان حيث يمكن لمكونات دورة الحياة إيقاف أي وظيفة لا تحتاج إلى تشغيل أثناء عدم ظهور المكون على الشاشة.

في دالة ()onStop ، يجب أن يقوم التطبيق بتحرير أو تعديل المصادر التي لا تكون مطلوبة عندما لا يكون التطبيق مرئي للمستخدم.

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

إستخدام ()onStop بدلاً من إستخدام ()onPause يضمن إستمرار العمل المرتبط بواجهة المستخدم، حتى عندما يشاهد المستخدم نشاطك في وضع تعدد النوافذ.

يجب أيضاً إستخدام ()onStop لتنفيذ عمليات إيقاف التشغيل الإجبارية لوحدة المعالجة المركزية CPU.

مثال، إذا لم تتمكن من العثور على وقت أكثر ملائمة لحفظ المعلومات في قاعدة بيانات، فيمكنك القيام بذلك أثناء ()onStop .

يوضح المثال التالي تطبيق ()onStop الذي يحفظ محتويات مسودة الملاحظة إلى التخزين الدائم:

KOTLIN

override fun onStop() {
    // call the superclass method first
    super.onStop()

    // save the note's current draft, because the activity is stopping
    // and we want to be sure the current note progress isn't lost.
    val values = ContentValues().apply {
        put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText())
        put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle())
    }

    // do this update in background on an AsyncQueryHandler or equivalent
    asyncQueryHandler.startUpdate(
            token,     // int token to correlate calls
            null,      // cookie, not used here
            uri,       // The URI for the note to update.
            values,    // The map of column names and new values to apply to them.
            null,      // No SELECT criteria are used.
            null       // No WHERE columns are used.
    )
}

JAVA

@Override
protected void onStop() {
    // call the superclass method first
    super.onStop();

    // save the note's current draft, because the activity is stopping
    // and we want to be sure the current note progress isn't lost.
    ContentValues values = new ContentValues();
    values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
    values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());

    // do this update in background on an AsyncQueryHandler or equivalent
    asyncQueryHandler.startUpdate (
            mToken,  // int token to correlate calls
            null,    // cookie, not used here
            uri,    // The URI for the note to update.
            values,  // The map of column names and new values to apply to them.
            null,    // No SELECT criteria are used.
            null     // No WHERE columns are used.
    );
}

 

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

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

عندما يدخل نشاطك في حالة التوقف، يبقى كائن النشاط مقيماً بالذاكرة: يحتفظ بكل معلومات الحالة والأعضاء..

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

التي تم إنشاؤها أثناء أي من دوال الإستدعاء السابقة للحالة التي تم إستئنافها. يستمر النظام أيضاً بتتبع الحالة الحالية..

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

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

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

في حزمة (مجموعة من أزواج “قيمة-مفتاح”) ويستعيدها إذا أنتقل المستخدم مرة أخرى إلى النشاط.

لمزيد من المعلومات حول إستعادة نشاط يعود إليه المستخدم، راجع حفظ وإستعادة حالة النشاط.

 

من حالة التوقف، يعود النشاط إما للتفاعل مع المستخدم، أو يتم إنهاء النشاط وإختفاؤه. إذا عاد النشاط، سوف يستدعي النظام ()onRestart.

إذا تم الإنتهاء من النشاط، سوف يستدعى النظام ()onDestroy . المقطع التالي يشرح الإستدعاء ()onDestroy .

 

 

 

 

 

فهم دورات حياة النشاط

 

()onDestroy

يتم إستدعاء ()onDestroy قبل إتلاف النشاط. يقوم النظام بهذا الإستدعاء إما بسبب:

1- تم الإنتهاء من النشاط ( لأن المستخدم النشاط كلياً أو بسبب إستدعاء ()finish على النشاط)

2- أو يقوم النظام بتدمير النشاط مؤقتاً بسبب تغيير التكوين (مثل تدوير الجهاز أو وضع تعدد النوافذ)

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

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

بدلاً من وضع المنطق في نشاطك لتحديد سبب تدميره، يجب عليك إستخدام كائن ViewModel لإحتواء بيانات المعاينة ذات الصلة بنشاطك.

إذا كان سيتم إعادة إنشاء النشاط بسبب تغيير في التكوين، فلن يتعين على ViewModel القيام بأي شيء..

طالما أنه سيتم الحفاظ عليه وإعطائه إلى مثيل النشاط التالي. إذا لم يتم إعادة إنشاء النشاط، فسيكون لدى ViewModel ..

إستدعاء دالة ()onCleared حيث يمكنها تنظيف أي بيانات يحتاج إليها قبل إتلافه.

يمكنك التمييز بين هذين السيناريوهين بإستخدام دالة ()isFinishing .

إذا أنتهى النشاط، فإن ()onDestroy هو إستدعاء دورة الحياة النهائي الذي يستقبله النشاط.

إذا تم إستدعاء ()onDestroy كنتيجة لتغير التكوين، سيقوم النظام على الفور بإنشاء مثيل نشاط جديد..

ثم يقوم بإستدعاء ()onCreate على ذلك المثيل الجديد في التكوين الجديد.

يجب أن يؤدي إستدعاء ()onDestroy إلى تحرير كافة الموارد التي لم يتم تحريرها بواسطة عمليات الإستدعاء السابقة مثل ()onStop .

 

 

 

 

 

فهم دورات حياة النشاط

 

حالة النشاط و الطرد من الذاكرة


يقوم النظام بقتل العمليات عندما يحتاج إلى تحرير ذاكرة الوصول العشوائي؛ تعتمد إحتمالية قيام النظام بقتل عملية معينة على حالة العملية في ذلك الوقت.

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

إحتمالية القتل حالة العمليه حالة النشاط
أقل في المقدمه (مركزه أو على وشك التركيز) Created إنشاء
Started بدء
Resumed إستئناف
أكثر في الخلف (فقدت التركيز) Paused توقف مؤقت
غالباً

في الخلف (غير مرئيه) Stopped توقف
فارغه Destroyed تدمير

الجدول 1. العلاقة بين دورة حياة العملية وحالة النشاط

 

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

مما يدمر ليس النشاط فحسب ولكن كل شيء آخر يعمل في العملية أيضاً. لمعرفة كيفية الحفاظ على حالة واجهة المستخدم لنشاطك..

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

يمكن للمستخدم أيضاً قتل عملية، بإستخدام مدير التطبيق في الإعدادات لقتل التطبيق المطابق.

لمزيد من المعلومات حول العمليات بشكلٍ عام، راجع العمليات والتسلسل.

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

 

 

 

فهم دورات حياة النشاط

 

حفظ وإستعادة حالة واجهة المستخدم المؤقتة


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

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

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

مع ذلك، قد يدمر النظام عملية التطبيق أثناء غياب المستخدم ويتوقف نشاطك.

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

بإستخدام مجموعة من ViewModel و ()onSaveInstanceState و / أو التخزين المحلي. لمعرفة المزيد حول توقعات المستخدمين إزاء سلوك النظام..

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

يوضح هذا القسم حالة المثيل وكيفية تنفيذ دالة ()onSaveInstance ، وهي إستدعاء على النشاط نفسه.

إذا كانت بيانات واجهة المستخدم بسيطة وخفيفة الوزن، مثل بيانات بدائية النوع أو كائن بسيط (مثل “السلسلة” String)..

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

على الرغم من ذلك، في معظم الحالات، يجب إستخدام كلٍ من ViewModel و ()onSaveInstanceState ..

(كما هو موضح في حفظ حالة واجهة المستخدم) حيث أن ()onSaveInstanceState تتحمل تكاليف التسلسل / إلغاء التسلسل.

 

 

 

 

فهم دورات حياة النشاط

 

حالة المثيل

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

زر “الرجوع” أو عندما يشير نشاطك إلى عملية تدميره من خلال إستدعاء دالة الإنهاء ()finish.

عندما يتم تدمير نشاطك بسبب قيام المستخدم بالضغط على “رجوع” أو بسبب إنهاء النشاط نفسه..

فإن مفهوم النظام والمستخدم لمثيل “النشاط”Activity هذا قد أنتهى إلى الأبد. في هذه السيناريوهات..

يتطابق توقع المستخدم مع سلوك النظام ولن يكون لديك أي عمل إضافي للقيام به.

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

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

مثيل جديد لهذا النشاط بإستخدام مجموعة من البيانات المحفوظة التي تصف حالة النشاط عند تدميره.

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

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

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

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

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

 

ملاحظة: حتى يتمكن نظام الأندرويد من إستعادة حالة المعاينات في نشاطك، يجب أن يكون لكل معاينه معرِّف فريد يتم توفيره بواسطة سمة المعرف android:id.

 

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

للحفاظ على أكثر من “كمية صغيرة جداً” من البيانات، يجب عليك إتباع نهج الدمج للحفاظ على البيانات، بإستخدام التخزين المحلي المستمر..

الدالة ()onSaveInstanceState ، والفئة ViewModel، كما هو موضح في حفظ حالات واجهة المستخدم.

 

 

 

 

فهم دورات حياة النشاط

 

حفظ حالة واجهة مستخدم بسيطة وخفيفة بإستخدام ()onSaveInstanceState

 

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

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

مثل النص الموجود في ودجت تحرير النص EditText أو موضع تمرير ودجت ListView.

لحفظ معلومات حالة مثيل إضافية لنشاطك، يجب عليك تجاوز ()onSaveInstanceState وإضافة أزواج “قيمة-مفتاح” إلى كائن “الحزمه” Bundle ..

الذي تم حفظه في حالة إتلاف نشاطك بشكلٍ غير متوقع. إذا قمت بتجاوز ()onSaveInstanceState ..

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

KOTLIN

override fun onSaveInstanceState(outState: Bundle?) {
    // Save the user's current game state
    outState?.run {
        putInt(STATE_SCORE, currentScore)
        putInt(STATE_LEVEL, currentLevel)
    }

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(outState)
}

companion object {
    val STATE_SCORE = "playerScore"
    val STATE_LEVEL = "playerLevel"
}

JAVA

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
// ...


@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, currentScore);
    savedInstanceState.putInt(STATE_LEVEL, currentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

 

 

ملاحظة: لا يتم إستدعاء ()onSaveInstanceState عندما يقوم المستخدم بإغلاق النشاط بشكلٍ صريح أو في حالات أخرى عند إستدعاء دالة الإنهاء ()finish.

 

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

إذا لم تحدث مثل هذه الفرصة، يجب عليك حفظ هذه البيانات أثناء إستخدام دالة ()onStop .

 

 

 

فهم دورات حياة النشاط

 

إستعادة حالة واجهة مستخدم النشاط بإستخدام حالة المثيل المحفوظ

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

تتلقى كل من دوال الإستدعاء ()onCreate و ()onRestoreInstanceState نفس الحزمة التي تحتوي على معلومات حالة المثيل.

لأن دالة ()onCreate تستدعى إما عندما يقوم النظام بإنشاء مثيل جديد لنشاطك أو يقوم بإعادة إنشاء مثيل سابق..

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

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

مثال، يوضح مقتطف الكود التالي كيف يمكنك إستعادة بعض بيانات الحالة في ()onCreate :

KOTLIN

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState) // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        with(savedInstanceState) {
            // Restore value of members from saved state
            currentScore = getInt(STATE_SCORE)
            currentLevel = getInt(STATE_LEVEL)
        }
    } else {
        // Probably initialize members with default values for a new instance
    }
    // ...
}

JAVA

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        currentScore = savedInstanceState.getInt(STATE_SCORE);
        currentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    // ...
}

 

 

بدلاً من إستعادة الحالة أثناء “الإنشاء” ()onCreate قد تختار تنفيذ ()onRestoreInstanceState ، الذي يستدعيه النظام بعد الداله ()onStart .

يقوم النظام بإستدعاء ()onRestoreInstanceState فقط إذا كانت هناك حالة محفوظة لإستعادتها، لذا لا تحتاج إلى التحقق مما إذا كانت الحزمة خالية:

KOTLIN

override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState)

    // Restore state members from saved instance
    savedInstanceState?.run {
        currentScore = getInt(STATE_SCORE)
        currentLevel = getInt(STATE_LEVEL)
    }
}

JAVA

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    currentScore = savedInstanceState.getInt(STATE_SCORE);
    currentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

 

تحذير: قم دائماً بإستدعاء التطبيق المتفوق لـ ()onRestoreInstanceState بحيث يمكن للتطبيق الإفتراضي إستعادة حالة التسلسل الهرمي لواجهة العرض.

 

 

 

 

فهم دورات حياة النشاط

 

التنقل بين الأنشطة


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

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

يغطي هذا القسم الموضوعات التي تحتاج إلى معرفتها لتنفيذ إنتقالات نشاط ناجحة.

تتضمن هذه المواضيع بدء نشاط من نشاط آخر، حفظ حالة النشاط، و إستعادة حالة النشاط.

 

 

 

فهم دورات حياة النشاط

 

بدء نشاط من نشاط آخر

غالباً ما يحتاج النشاط إلى بدء نشاط آخر في مرحلة ما. تنشأ هذه الحاجة.

على سبيل المثال، عندما يحتاج التطبيق إلى الإنتقال من الشاشة الحالية إلى شاشة جديدة.

إستناداً إلى ما إذا كان نشاطك يريد نتيجةً من النشاط الجديد الذي هو على وشك تشغيله، يمكنك بدء النشاط الجديد إما..

بإستخدام ()startActivity أو دالة ()startActivityForResult . في كلتا الحالتين، تقوم بالتمرير في كائن غرض.

يحدد كائن الغرض إما النشاط الدقيق الذي تريد بدءه أو يصف نوع الإجراء الذي تريد تنفيذه (ويختار النظام النشاط المناسب لك، والذي يمكن أن يكون من تطبيق مختلف).

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

 

 

 

 

فهم دورات حياة النشاط

 

()startActivity

إذا لم يكن النشاط الذي بدأ حديثاً بحاجة إلى إرجاع نتيجة، يمكن أن يبدأه النشاط الحالي من خلال إستدعاء الداله ()startActivity.

عند العمل ضمن تطبيقك، تحتاج غالباً إلى بدء نشاط معروف.

مثال، يعرض مقتطف الكود التالي كيفية تشغيل نشاط يسمى “نشاط تسجيل الدخول” SignInActivity.

KOTLIN

val intent = Intent(this, SignInActivity::class.java)
startActivity(intent)

JAVA

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

 

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

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

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

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

إذا كان هناك العديد من الأنشطة التي يمكنها أن تتعامل مع الغرض، فيمكن للمستخدم إختيار أي منها ليستخدمه.

على سبيل المثال، إذا كنت تريد السماح للمستخدم بإرسال رسالة بريد إلكتروني، فيمكنك إنشاء الغرض التالي:

KOTLIN

val intent = Intent(Intent.ACTION_SEND).apply {
    putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)

JAVA

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

 

إضافة EXTRA_EMAIL الإضافية إلى الغرض، هي “مصفوفة سلسله” من عناوين البريد الإلكتروني التي يجب إرسال البريد الإلكتروني إليها.

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

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

 

 

 

 

فهم دورات حياة النشاط

 

()startActivityForResult

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

إختيار شخص في قائمة جهات الإتصال؛ عندما ينتهي، فإنه يقوم بإرجاع الشخص الذي تم تحديده.

للقيام بذلك، يمكنك إستدعاء الدالة (startActivityForResult(Intent، int ، حيث يعّرف المعامل “عدد صحيح”، الإستدعاء.

الغرض من هذا المعرّف هو إزالة الغموض بين الإستدعاءات المتعددة لـ (startActivityForResult(Intent، int من نفس النشاط.

إنه ليس معرّف عالمي “عام” ولا يتعارض مع التطبيقات أو الأنشطة الأخرى. وتأتي النتيجة مرة أخرى من خلال دالة (onActivityResult(int، int، Intent.

عند إنهاء نشاط تابع، يمكنه إستدعاء (setResult(int لإرجاع البيانات إلى أصلها. يجب أن يقوم النشاط التابع دائماً بتوفير كود النتيجة..

والذي يمكن أن يكون النتيجة القياسية RESULT_CANCELED أو RESULT_OK أو أي قيم مخصصة تبدأ من RESULT_FIRST_USER.

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

يستخدم النشاط الأصل دالة (onActivityResult(int ، int ، Intent ، إلى جانب مُعرّف العدد الصحيح الذي قدمه النشاط الأصل أساساً، لتلقي المعلومات.

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

KOTLIN

class MyActivity : Activity() {
    // ...

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
            // When the user center presses, let them pick a contact.
            startActivityForResult(
                    Intent(Intent.ACTION_PICK,Uri.parse("content://contacts")),
                    PICK_CONTACT_REQUEST)
            return true
        }
        return false
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
        when (requestCode) {
            PICK_CONTACT_REQUEST ->
                if (resultCode == RESULT_OK) {
                    startActivity(Intent(Intent.ACTION_VIEW, intent?.data))
                }
        }
    }

    companion object {
        internal val PICK_CONTACT_REQUEST = 0
    }
}

JAVA

public class MyActivity extends Activity {
     // ...

     static final int PICK_CONTACT_REQUEST = 0;

     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
             // When the user center presses, let them pick a contact.
             startActivityForResult(
                 new Intent(Intent.ACTION_PICK,
                 new Uri("content://contacts")),
                 PICK_CONTACT_REQUEST);
            return true;
         }
         return false;
     }

     protected void onActivityResult(int requestCode, int resultCode,
             Intent data) {
         if (requestCode == PICK_CONTACT_REQUEST) {
             if (resultCode == RESULT_OK) {
                 // A contact was picked.  Here we will just display it
                 // to the user.
                 startActivity(new Intent(Intent.ACTION_VIEW, data));
             }
         }
     }
 }

 

 

 

 

 

فهم دورات حياة النشاط

 

تنسيق الأنشطة

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

يتوقف النشاط الأول عن التشغيل ويدخل في حالة الإيقاف المؤقت أو حالة التوقف، بينما يتم إنشاء النشاط الآخر.

في حالة مشاركة هذه الأنشطة للبيانات المحفوظة على القرص أو في أي مكان آخر، من المهم أن نفهم أن النشاط الأول لا يتوقف تماماً قبل أن يتم إنشاء النشاط الثاني.

في الواقع، تتداخل عملية بدء النشاط الثاني مع عملية إيقاف النشاط الأول.

يتم تحديد ترتيب عمليات الإستدعاء في دورة الحياة بشكلٍ جيد، خاصة عندما يكون النشاطان في نفس العملية (التطبيق) وأحدهما يبدأ الآخر.

في ما يلي ترتيب العمليات التي تحدث عندما يبدأ النشاط أ بتشغيل النشاط ب:

1- يتم تنفيذ دالة ()onPause للنشاط أ.

2- يتم تنفيذ دوال ()onCreate و ()onStart و ()onResume للنشاط B بالتسلسل. (النشاط ب لديه تركيز المستخدم الآن.)

3- ثم، إذا لم يعد النشاط A مرئياً على الشاشة، فسيتم تنفيذ دالة ()onStop الخاصة به.

 

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

 

 


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

الإعلانات

10 thoughts on “دورات حياة النشاط”

اترك رد