الأربعاء، 18 أكتوبر 2017

أنشطة Activities



أنشطة Activities






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

إدارة الأنشطة بمهارة تسمح لك للتأكد، على سبيل المثال:

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

المزيد من الموارد
API GUIDES
Application Fundamentals
Android apps are written in the Java programming language. The Android SDK tools compile your code along with any data and resource files into an APK, an Android package , which is an archive file with an apk suffix. One APK file contains all the contents…
API GUIDES
Intents and Intent Filters
An Intent is a messaging object you can use to request an action from another app component . Although intents facilitate communication between components in several ways, there are three fundamental use cases: An Activity represents a single screen in…
TRAINING
Building Your First App
If you're new to Android app development, this where you should begin. This series of lessons shows you how to create a new project, build a simple app, and run it on a device or emulator.



مقدمة في الأنشطة

في هذه الوثيقة
مفهوم الأنشطة
تكوين البيان
أعلن الأنشطة
إعلان فلاتر النوايا
أعلن الأذونات
إدارة دورة حياة النشاط
OnCreate الخاص ()
onStart ()
onResume ()
onPause ()
onStop ()
onRestart ()
onDestroy ()



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


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


مفهوم الأنشطة

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

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


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


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


تكوين البيان

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

أعلن الأنشطة

لإعلان نشاطك، افتح ملف البيان وأضف عنصرا <نشاط> كطفل من عنصر <أبليكاتيون> . فمثلا:
<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >
السمة المطلوبة فقط لهذا العنصر هو الروبوت: الاسم ، الذي يحدد اسم فئة النشاط. يمكنك أيضا إضافة سمات تحدد خصائص النشاط مثل التصنيف أو الرمز أو مظهر واجهة المستخدم. لمزيد من المعلومات حول هذه السمات وغيرها، راجع وثائق <أكتيفيتي> مرجع العنصر.

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


إعلان فلاتر النوايا

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

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


<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">

    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
<activity>

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


// Create the text message with a string

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Start the activity
startActivity(sendIntent);


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

أعلن الأذونات
يمكنك استخدام علامة <activity> في البيان للتحكم في التطبيقات التي يمكنها بدء نشاط معين. لا يمكن لنشاط الوالد إطلاق نشاط فرعي إلا إذا كان النشاطان لهما نفس الأذونات في البيان. إذا كنت تعلن عن عنصر <uses-permission> لنشاط معين، فيجب أن يحتوي النشاط المتصل على عنصر <uses-permission> مطابق.

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



<manifest>

<activity android:name="...."
   android:permission=”com.google.socialapp.permission.SHARE_POST”

/>

ثم، ليتم السماح له بالاتصال سوسيالب، يجب أن تطابق التطبيق الخاص بك إذن تعيين في بيان سوسيالاب ل:

<manifest>

   <uses-permission android:name="com.google.socialapp.permission.SHARE_POST" />
</manifest>

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


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

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

OnCreate الخاص ()

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

عند onCreate() ، يكون رد الاتصال التالي دائما onStart() .


onStart ()

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

onResume ()

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

onPause() الاستدعاء onPause() دائما على onResume() .


onPause ()

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

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


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


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


onStop ()

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

الاستدعاء التالي الذي يدعو النظام إما على onRestart() ، إذا كان النشاط يعود إلى التفاعل مع المستخدم، أو بواسطة onDestroy() إذا كان هذا النشاط هو إنهاء تماما.


onRestart ()

النظام استدعاء هذا الاستدعاء عند نشاط في حالة ستوبد على وشك إعادة تشغيل. onRestart() يستعيد حالة النشاط من الوقت الذي تم فيه إيقافه.

ويتبع هذا الاستدعاء دائما onStart() .


onDestroy ()

يستدعي النظام هذا الرد قبل أن يتم تدمير النشاط.

هذا الرد هو الأخير الذي يتلقى النشاط. onDestroy() عادة ما يتم تنفيذها لضمان أن يتم تحرير جميع الموارد النشاط عندما يتم تدمير النشاط، أو العملية التي تحتوي على ذلك.


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


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

في هذه الوثيقة
مفاهيم دورة حياة النشاط
ردات دورة الحياة
OnCreate الخاص ()
onStart ()
onResume ()
onPause ()
onStop ()
onDestroy ()
حالة النشاط وطرد من الذاكرة
التنقل بين الأنشطة
بدء نشاط واحد من آخر
حفظ واستعادة الدولة النشاط
عندما يتنقل المستخدم عبر تطبيقك والخروج منه والعودة إليه، يتم Activity مثيلات Activity في عملية نقل التطبيق عبر حالات مختلفة في دورة حياته. توفر فئة Activity عددا من عمليات الاستدعاء التي تسمح للنشاط بمعرفة أن حالة قد تغيرت: أن النظام يقوم بإنشاء أو إيقاف أو استئناف نشاط ما أو تدمير العملية التي يوجد فيها النشاط.

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


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

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

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


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

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

يعرض الشكل 1 تمثيل مرئي لهذا النموذج.



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





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


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


يقدم القسم التالي من هذه الوثيقة تفاصيل حول عمليات الرد التي تستخدمها للتعامل مع التحولات بين الدول.


ردات دورة الحياة

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

OnCreate الخاص ()

يجب تنفيذ هذا الرد، الذي ينطلق عندما يقوم النظام أولا بإنشاء النشاط. عند إنشاء النشاط، يدخل النشاط الحالة كريتد . في أسلوب onCreate() ، تقوم بتنفيذ المنطق الأساسي لبدء تشغيل التطبيق الذي يجب أن يحدث مرة واحدة فقط طوال عمر النشاط. على سبيل المثال، قد يؤدي onCreate() إلى ربط البيانات بالقوائم، وتهيئة مؤشرات الترابط الخلفية، وبدء بعض متغيرات النطاق. تتلقى هذه الطريقة المعلمة savedInstanceState ، وهو كائن Bundle يحتوي على حالة النشاط المحفوظة مسبقا. إذا كان النشاط لم يكن موجودا من قبل، قيمة الكائن " Bundle فارغة.

يعرض المثال التالي على أسلوب onCreate() الإعداد الأساسي للنشاط، مثل تعريف واجهة المستخدم (المعرفة في ملف تخطيط شمل)، وتعريف متغيرات الأعضاء، وتكوين بعض واجهة المستخدم. في هذا المثال، يتم تحديد ملف تخطيط شمل عن طريق تمرير معرف مورد الملف R.layout.main_activity إلى setContentView() .



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 previously saved 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);
}

كبديل لتعريف ملف شمل وتمريره إلى setContentView() ، يمكنك إنشاء كائنات View جديدة في كود النشاط الخاص بك وبناء تسلسل هرمي للعرض عن طريق إدراج View جديد s في مجموعة ViewGroup . ثم يمكنك استخدام هذا التخطيط عن طريق تمرير الجذر ViewGroup إلى setContentView() . لمزيد من المعلومات حول إنشاء واجهة مستخدم، راجع وثائق واجهة المستخدم .


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


onStart ()

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

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


onResume ()

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

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


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



@Override

public void onResume() {
    super.onResume();  // Always call the superclass method first


    // Get the Camera instance as the activity achieves full user focus

    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}


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


onPause ()

ويدعو النظام هذه الطريقة كأول دلالة على أن المستخدم يغادر نشاطك (على الرغم من أنه لا يعني دائما أن النشاط يجري تدميره). استخدام أسلوب onPause() لإيقاف عمليات مثل هذه الرسوم المتحركة وتشغيل الموسيقى التي يجب أن لا تستمر أثناء Activity في الحالة متوقفة مؤقتا، والتي تتوقع استئنافها قريبا. هناك العديد من الأسباب التي تجعل النشاط قد يدخل هذه الحالة. فمثلا:

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

في الروبوت 7.0 (أبي مستوى 24) أو أعلى، وتطبيقات متعددة تعمل في وضع متعددة نافذة. لأن واحد فقط من تطبيقات (ويندوز) لديه التركيز في أي وقت، ونظام يوقف كل من التطبيقات الأخرى.
يتم فتح نشاط جديد شبه شفاف (مثل مربع حوار). طالما أن النشاط لا يزال مرئيا جزئيا ولكن ليس في التركيز، فإنه لا يزال متوقفا مؤقتا.
يمكنك استخدام أسلوب onPause() لإطلاق موارد النظام مثل أجهزة استقبال البث أو مقابض أجهزة الاستشعار (مثل نظام تحديد المواقع العالمي) أو أي موارد قد تؤثر على عمر البطارية أثناء توقف نشاطك مؤقتا ولا يحتاج المستخدم إليها.

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


@Override

public void onPause() {
    super.onPause();  // Always call the superclass method first


    // Release the Camera because we don't need it when paused

    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}


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


إكمال أسلوب onPause() لا يعني أن النشاط يترك الحالة المتوقفة مؤقتا. بدلا من ذلك، يبقى النشاط في هذه الحالة حتى يستأنف النشاط أو يصبح غير مرئي تماما للمستخدم. في حالة استئناف النشاط، يستدعي النظام مرة أخرى استدعاء onResume() . إذا عاد النشاط من الحالة متوقفة مؤقتا إلى حالة مستأنف، يحتفظ النظام مثيل Activity المقيمين في الذاكرة، استدعاء هذا المثيل عند استدعاء النظام onResume() . في هذا السيناريو، لا تحتاج إلى إعادة تهيئة المكونات التي تم إنشاؤها أثناء أي من أساليب رد الاتصال المؤدية إلى الحالة المستأنفة. إذا أصبح النشاط غير مرئي تماما، يستدعي النظام onStop() . يناقش القسم التالي onStop() .


onStop ()

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

في طريقة onStop() ، يجب أن التطبيق الافراج عن جميع الموارد تقريبا التي ليست هناك حاجة في حين أن المستخدم لا يستخدم ذلك. على سبيل المثال، إذا قمت بتسجيل BroadcastReceiver في onStart() للاستماع إلى التغييرات التي قد تؤثر على واجهة المستخدم الخاصة بك، يمكنك إلغاء تسجيل جهاز استقبال البث في onStop() ، حيث لا يمكن للمستخدم رؤية واجهة المستخدم. ومن المهم أيضا أن تستخدم onStop() لإطلاق الموارد التي قد تسرب الذاكرة، لأنه من الممكن للنظام لقتل عملية استضافة نشاطك دون استدعاء النهائي رد على رد النشاط onDestroy() .


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


@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

    mAsyncQueryHandler.startUpdate (
            mToken,  // int token to correlate calls
            null,    // cookie, not used here
            mUri,    // 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.
    );
}


عندما يدخل النشاط الخاص بك حالة ستوبد، يتم الاحتفاظ كائن Activity المقيمين في الذاكرة: يحافظ على كافة معلومات الدولة والعضو، ولكن لا تعلق على مدير النوافذ. عند استئناف النشاط، يشير النشاط إلى هذه المعلومات. لا تحتاج إلى إعادة تهيئة المكونات التي تم إنشاؤها أثناء أي من أساليب رد الاتصال المؤدية إلى الحالة المستأنفة. النظام أيضا بتتبع الحالة الحالية لكل كائن View في التخطيط، لذلك إذا أدخل المستخدم النص إلى عنصر واجهة مستخدم EditText ، يتم الاحتفاظ بهذا المحتوى بحيث لا تحتاج إلى حفظ واستعادته.


ملاحظة: بمجرد إيقاف نشاطك، قد يقوم النظام بتدمير العملية التي تحتوي على النشاط إذا كان النظام يحتاج إلى ذاكرة الاسترداد. حتى إذا كان النظام يدمر العملية أثناء إيقاف النشاط، فإن النظام لا يزال يحتفظ بحالة الكائنات View (مثل النص في عنصر واجهة مستخدم EditText ) في Bundle (نقطة من أزواج مفتاح القيمة) ويستعيدها إذا كان المستخدم يتنقل مرة أخرى إلى النشاط. لمزيد من المعلومات حول استعادة النشاط الذي يقوم المستخدم بإرجاعه، راجع حفظ حالة النشاط واستعادتها .


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


onDestroy ()

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

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


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

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

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


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


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

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

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


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

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

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

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

اعتمادا على ما إذا كان نشاطك يريد نتيجة من النشاط الجديد على وشك البدء، بدء النشاط الجديد باستخدام إما startActivity() أو startActivityForResult() الأسلوب. في كلتا الحالتين، يمكنك تمرير في كائن Intent .


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


startActivity ()

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

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



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

startActivity(intent);

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



Intent intent = new Intent(Intent.ACTION_SEND);

intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);


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


startActivityForResult ()

في بعض الأحيان كنت ترغب في الحصول على نتيجة مرة أخرى من النشاط عندما ينتهي. على سبيل المثال، يمكنك بدء نشاط يتيح للمستخدم اختيار شخص في قائمة جهات الاتصال. عندما ينتهي، فإنه يعود الشخص الذي تم اختياره. للقيام بذلك، استدعاء الأسلوب startActivityForResult(Intent, int) ، حيث تحدد المعلمة صحيح المكالمة. ويهدف هذا المعرف إلى startActivityForResult(Intent, int) بين مكالمات متعددة startActivityForResult(Intent, int) من نفس النشاط. انها ليست معرف عالمي وليس في خطر تتعارض مع تطبيقات أو أنشطة onActivityResult(int, int, Intent) تأتي مرة أخرى من خلال onActivityResult(int, int, Intent) .

عند خروج نشاط الطفل، يمكن استدعاء setResult(int) لإرجاع البيانات إلى الأصل. يجب أن يقدم نشاط الطفل دائما شفرة نتيجة، والتي يمكن أن تكون النتائج القياسية RESULT_CANCELED ، RESULT_OK ، أو أية قيم مخصصة تبدأ من RESULT_FIRST_USER . بالإضافة إلى ذلك، يمكن نشاط الطفل اختياريا كائن Intent تحتوي على أي بيانات إضافية يريد. يستخدم النشاط الأصل طريقة onActivityResult(int, int, Intent) ، جنبا إلى جنب مع معرف صحيح النشاط الأصلي الموردة أصلا، لتلقي المعلومات.


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



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));
             }
         }
     }
 }

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

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

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


يتم تنفيذ الأسلوب onPause() .

يتم تنفيذ أساليب النشاط onCreate() ، onStart() ، و onResume() في التسلسل. (النشاط B الآن لديه تركيز المستخدم.)
ثم، إذا لم يعد النشاط أ مرئيا على الشاشة، onStop() تنفيذ طريقة onStop() .
يسمح هذا التسلسل القابل للتنبؤ من استدعاءات دورة الحياة بإدارة نقل المعلومات من نشاط إلى آخر.

حفظ واستعادة الدولة النشاط

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

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


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


حفظ حالة النشاط الخاص بك

عندما يبدأ نشاطك في التوقف، يقوم النظام باستدعاء الأسلوب onSaveInstanceState() بحيث يمكن للنشاط الخاص بك حفظ معلومات الحالة مع مجموعة من أزواج القيمة الرئيسية. التنفيذ الافتراضي لهذه الطريقة يوفر معلومات عابرة حول حالة التسلسل الهرمي عرض النشاط، مثل النص في عنصر واجهة مستخدم EditText أو موقف التمرير ListView واجهة مستخدم EditText . يجب تطبيق التطبيق الخاص بك استدعاء onPause() أسلوب onStop() وقبل onStop() . لا تقم بتنفيذ هذا الاستدعاء في onPause() .

تحذير: يجب دائما استدعاء تنفيذ onSaveInstanceState() بحيث يمكن تنفيذ الافتراضي حفظ حالة التسلسل الهرمي عرض.


لحفظ معلومات حالة إضافية للنشاط الخاص بك، يجب تجاوز onSaveInstanceState() وإضافة أزواج قيمة مفتاح إلى الكائن Bundle التي يتم حفظها في الحدث الذي يتم تدمير نشاطك بشكل غير متوقع. فمثلا:



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, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);


    // Always call the superclass so it can save the view hierarchy state

    super.onSaveInstanceState(savedInstanceState);
}


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


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


استعادة حالة النشاط الخاص بك

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

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


على سبيل المثال، يظهر مقتطف الشفرة التالي كيف يمكنك استعادة بعض بيانات الحالة في onCreate() :


@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
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

تحذير: دائما استدعاء تنفيذ onRestoreInstanceState() بحيث يمكن تنفيذ الافتراضي استعادة حالة التسلسل الهرمي عرض.



تغييرات حالة النشاط



في هذه الوثيقة

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

لمزيد من المعلومات حول حالات النشاط، راجع دورة حياة النشاط .


يحدث تغيير التكوين

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

عند حدوث تغيير في التكوين، يتم تدمير النشاط وإعادة إنشائه. إذا كنت ترغب في الحفاظ على بيانات حالة عابرة للنشاط، يجب تجاوز أسلوب onSaveInstanceState() لحفظ البيانات، ثم استخدم onCreate() أو onRestoreInstanceState() استرجاع لإعادة إنشاء حالة المثيل.


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


التعامل مع الحالات متعددة النوافذ

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

للحصول على مزيد من المعلومات حول دورة حياة متعددة الإطار، راجع المقطع دورة حياة متعددة نافذة من صفحة " دعم متعدد النوافذ" .


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


عندما يقوم المستخدم بالتبديل من التطبيق A إلى التطبيق B، يقوم النظام باستدعاء onPause() على التطبيق A و onResume() على التطبيق B. ويتحول بين هاتين الطريقتين في كل مرة يقوم المستخدم فيها بالتبديل بين التطبيقات.


لمزيد من التفاصيل حول تعدد النوافذ، ارجع إلى دعم النوافذ المتعددة .


يظهر النشاط أو مربع الحوار في المقدمة

في حالة ظهور نشاط أو مربع حوار جديد في المقدمة، مع التركيز والغطاء الجزئي للنشاط قيد التقدم، يفقد النشاط المغطى التركيز ويدخل الحالة المتوقفة مؤقتا. ثم، يدعو النظام onResume() على ذلك.

عندما يعود النشاط المغطى إلى المقدمة ويستعيد التركيز، فإنه يدعو onResume() .


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


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


ملاحظة: عندما ينقر المستخدم على زر "نظرة عامة" أو "الصفحة الرئيسية"، يتصرف النظام كما لو كان النشاط الحالي قد تم تغطيته بالكامل.


الصنابير المستخدم زر الرجوع

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

من المهم ملاحظة أنه بشكل افتراضي، لا يتم تشغيل استدعاء onSaveInstanceState() في هذه الحالة. ويستند هذا السلوك على افتراض أن المستخدم استغلالها زر العودة مع أي توقع للعودة إلى نفس المثال من النشاط. ومع ذلك، يمكنك تجاوز الأسلوب onBackPressed() لتنفيذ بعض السلوك المخصص، على سبيل المثال الحوار "تأكيد-إنهاء".



إذا onBackPressed() الأسلوب onBackPressed() ، فإننا لا نزال نوصي بشدة باستدعاء super.onBackPressed() من الأسلوب super.onBackPressed() . وإلا فإن سلوك زر الرجوع قد يكون التنافر للمستخدم.

المهام والعودة المكدس



في هذه الوثيقة

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


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



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


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


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



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









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







الشكل 2. مهمتان: تتلقى المهمة B تفاعل المستخدم في المقدمة، بينما المهمة A في الخلفية، في انتظار استئنافها.


الشكل 3. يتم إنشاء نشاط واحد عدة مرات.


المهمة هي وحدة متماسكة يمكنها الانتقال إلى "الخلفية" عند بدء المستخدمين لمهمة جديدة أو الانتقال إلى الشاشة الرئيسية، عبر زر الصفحة الرئيسية . بينما في الخلفية، يتم إيقاف جميع الأنشطة في المهمة، ولكن المكدس الخلفي للمهمة لا يزال سليما - المهمة فقدت ببساطة التركيز في حين أن مهمة أخرى تجري، كما هو مبين في الشكل 2. ويمكن للمهمة ثم العودة إلى " الأمامية "بحيث يمكن للمستخدمين التقاط حيث توقفوا. لنفترض، على سبيل المثال، أن المهمة الحالية (المهمة أ) لديها ثلاثة أنشطة في كومة اثنين تحت النشاط الحالي. يضغط المستخدم على زر الصفحة الرئيسية ، ثم يبدأ تطبيق جديد من مشغل التطبيقات. عند ظهور الشاشة الرئيسية، تنتقل المهمة A إلى الخلفية. عندما يبدأ التطبيق الجديد، يبدأ النظام مهمة لهذا التطبيق (المهمة B) مع كومة الخاصة بها من الأنشطة. بعد التفاعل مع هذا التطبيق، يقوم المستخدم بإرجاع الصفحة الرئيسية مرة أخرى ويختار التطبيق الذي بدأ في الأصل المهمة A. الآن، المهمة A تأتي في المقدمة - جميع الأنشطة الثلاثة في كومة سليمة والنشاط في الجزء العلوي من المكدس يستأنف. عند هذه النقطة، يمكن للمستخدم أيضا التبديل مرة أخرى إلى المهمة B عن طريق الذهاب الرئيسية واختيار رمز التطبيق الذي بدأ تلك المهمة (أو عن طريق تحديد مهمة التطبيق من الشاشة الأخيرة ). هذا مثال على تعدد المهام على الروبوت.

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


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


لتلخيص السلوك الافتراضي للأنشطة والمهام:


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

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

يمكنك القيام بهذه الأشياء وأكثر من ذلك، مع سمات في العنصر <activity> البيان ومع الأعلام في القصد أن تمرر startActivity() .


في هذا الصدد، السمات الرئيسية <activity> التي يمكنك استخدامها هي:


taskAffinity

launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
وأهم أهداف النوايا التي يمكنك استخدامها هي:

FLAG_ACTIVITY_NEW_TASK

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

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


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


تحديد طرق الإطلاق

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

استخدام ملف البيان

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

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


استخدام ملف البيان

عند إعلان نشاط في ملف البيان، يمكنك تحديد كيفية ارتباط النشاط بمهمة باستخدام السمة launchMode <activity> للعنصر.

تحدد السمة launchMode تعليمات حول كيفية تشغيل النشاط إلى مهمة. هناك أربع طرق إطلاق مختلفة يمكنك تعيين سمة launchMode :


"standard" (الوضع الافتراضي)

افتراضي. يقوم النظام بإنشاء مثيل جديد للنشاط في المهمة التي تم بدء تشغيلها وتوجيه النية إليه. النشاط يمكن أن تكون مثبتة عدة مرات، كل حالة يمكن أن تنتمي إلى مهام مختلفة، ومهمة واحدة يمكن أن يكون مثيلات متعددة.
"singleTop"
إذا كان مثيل النشاط موجود بالفعل في أعلى المهمة الحالية، يقوم النظام بتوجيه النية إلى هذا المثيل من خلال استدعاء أسلوب onNewIntent() بدلا من إنشاء مثيل جديد للنشاط. يمكن أن يتم تنشيط النشاط مرات متعددة، كل حالة يمكن أن تنتمي إلى مهام مختلفة، ومهمة واحدة يمكن أن يكون مثيلات متعددة (ولكن فقط إذا كان النشاط في الجزء العلوي من كومة الخلفي ليست مثيل موجود من النشاط).
على سبيل المثال، لنفترض أن المكدس الخلفي للمهمة يتكون من نشاط الجذر A مع الأنشطة B و C و D على القمة (المكدس أبسد؛ D على القمة). نية تصل لنشاط من نوع D. إذا كان D وضع التشغيل الافتراضي "standard" ، يتم تشغيل مثيل جديد من فئة والمكدس يصبح أبسد. ومع ذلك، إذا كان وضع الإطلاق D هو "singleTop" ، فإن المثيل الحالي من D يتلقى النية من خلال onNewIntent() ، لأنه في الجزء العلوي من المكدس - تبقى المكدس أبسد. ومع ذلك، إذا وصلت نية لنشاط من النوع B، ثم يتم إضافة مثيل جديد من B إلى المكدس، حتى لو كان وضع إطلاقه هو "singleTop" .

ملاحظة: عند إنشاء مثيل جديد للنشاط، يمكن للمستخدم الضغط على الزر " رجوع" للعودة إلى النشاط السابق. ولكن عندما تقوم حالة موجودة من نشاط يعالج نية جديدة، لا يمكن للمستخدم الضغط على زر العودة للعودة إلى حالة النشاط قبل وصول نية جديدة في onNewIntent() .


"singleTask"

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

"singleInstance" .

نفس "singleTask" ، إلا أن النظام لا تطلق أي أنشطة أخرى في مهمة عقد المثيل. والنشاط هو دائما العضو الوحيد والوحيد في مهمته؛ أي أنشطة بدأها هذا واحد مفتوح في مهمة منفصلة.
وكمثال آخر، يعلن تطبيق أندرويد بروزر أن نشاط متصفح الويب يجب أن يفتح دائما في مهمته الخاصة - من خلال تحديد وضع تشغيل singleTask في عنصر <activity> . وهذا يعني أنه إذا كان تطبيقك ينوي فتح متصفح أندرويد، فلن يتم وضع نشاطه في نفس مهمة تطبيقك. بدلا من ذلك، إما تبدأ مهمة جديدة للمتصفح أو، إذا كان المتصفح لديه بالفعل مهمة قيد التشغيل في الخلفية، يتم إحضار هذه المهمة إلى الأمام للتعامل مع القصد الجديد.

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




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


لمزيد من المعلومات حول استخدام أوضاع التشغيل في ملف البيان، راجع وثائق عنصر <activity> ، حيث يتم launchMode السمة launchMode والقيم المقبولة أكثر.


ملاحظة: يمكن تجاوز السلوكيات التي تحددها لنشاطك مع السمة launchMode بواسطة الأعلام المضمنة بقصد بدء النشاط الخاص بك كما هو موضح في المقطع التالي.


استخدام أعلام النوايا

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

FLAG_ACTIVITY_NEW_TASK

بدء النشاط في مهمة جديدة. إذا كانت إحدى المهام قيد التشغيل بالفعل للنشاط الذي تقوم به الآن، يتم إحضار هذه المهمة إلى المقدمة مع استعادة آخر حالة لها ويتلقى النشاط النية الجديدة في onNewIntent() .
هذا ينتج نفس السلوك مثل "singleTask" قيمة launchMode ، التي نوقشت في القسم السابق.

FLAG_ACTIVITY_SINGLE_TOP

إذا كان النشاط الذي يتم تشغيله هو النشاط الحالي (في أعلى كومة الظهر)، ثم يتلقى المثيل الحالي مكالمة إلى onNewIntent() ، بدلا من إنشاء مثيل جديد من النشاط.
هذا ينتج نفس السلوك مثل "singleTop" قيمة launchMode ، التي نوقشت في المقطع السابق.

FLAG_ACTIVITY_CLEAR_TOP

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

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


ملاحظة: إذا كان وضع إطلاق النشاط المعين هو "standard" ، فإنه يتم أيضا إزالة من المكدس ويتم إطلاق مثيل جديد في مكانها للتعامل مع القصد واردة. وذلك لأن مثيل جديد يتم إنشاؤه دائما لنوايا جديدة عندما يكون وضع الإطلاق "standard" .


التعامل مع أوجه الانتماء

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

يمكنك تعديل مدى التقارب لأي نشاط معين مع السمة taskAffinity <activity> .


تأخذ السمة taskAffinity قيمة سلسلة، والتي يجب أن تكون فريدة من اسم الحزمة الافتراضية المعلنة في العنصر <manifest> ، لأن النظام يستخدم هذا الاسم لتحديد تقارب المهمة الافتراضية للتطبيق.


يأتي التقارب في ظروف اثنين:


عندما يتضمن النية التي تطلق نشاطا العلم FLAG_ACTIVITY_NEW_TASK .

يتم إطلاق نشاط جديد، بشكل افتراضي، في مهمة النشاط الذي يسمى startActivity() . انها دفعت على نفس كومة الخلفي كما المتصل. ومع ذلك، إذا كانت النية التي تم تمريرها startActivity() تحتوي على علامة FLAG_ACTIVITY_NEW_TASK ، فإن النظام يبحث عن مهمة مختلفة لاستيعاب النشاط الجديد. في كثير من الأحيان، انها مهمة جديدة. ومع ذلك، فإنه لا يجب أن يكون. إذا كان هناك بالفعل مهمة موجودة بنفس التقارب مع النشاط الجديد، يتم تشغيل النشاط في هذه المهمة. إن لم يكن، فإنه يبدأ مهمة جديدة.
إذا تسبب هذا العلم نشاط لبدء مهمة جديدة ويضغط المستخدم على زر الصفحة الرئيسية لترك الأمر، يجب أن يكون هناك بعض الطريق للمستخدم للانتقال إلى المهمة. بعض الكيانات (مثل مدير الإعلام) تبدأ دائما الأنشطة في مهمة خارجية، أبدا كجزء من تلقاء نفسها، لذلك يضعون دائما FLAG_ACTIVITY_NEW_TASK في النوايا التي يمرون startActivity() . إذا كان لديك نشاط يمكن استدعاؤه بواسطة كيان خارجي قد يستخدم هذه العلامة، فاحرص على أن يكون لدى المستخدم طريقة مستقلة للعودة إلى المهمة التي بدأت، مثل رمز قاذفة (النشاط الجذر للمهمة لديه فلتر القصد CATEGORY_LAUNCHER ؛ راجع قسم بدء مهمة أدناه).
عندما يكون النشاط له allowTaskReparenting المميزة allowTaskReparenting تعيين "true" allowTaskReparenting "true" .
في هذه الحالة، يمكن للنشاط أن ينتقل من المهمة التي تبدأ إلى المهمة التي لديها تقارب ل، عندما تأتي هذه المهمة إلى المقدمة.
على سبيل المثال، لنفترض أن النشاط الذي يبلغ عن الأحوال الجوية في مدن مختارة يتم تعريفه كجزء من تطبيق السفر. لديها نفس تقارب الأنشطة الأخرى في نفس التطبيق (التقارب التطبيق الافتراضي) ويسمح إعادة الأبوة والأمومة مع هذه السمة. عندما يبدأ أحد أنشطتك نشاط مراسل الطقس، فإنه ينتمي في البداية إلى نفس مهمة نشاطك. ومع ذلك، عندما يأتي مهمة التطبيق السفر إلى المقدمة، يتم إعادة تعيين النشاط مراسل الطقس لهذه المهمة وعرضها داخله.
نصيحة: إذا كان ملف أبك يحتوي على أكثر من "تطبيق" واحد من وجهة نظر المستخدم، فربما تريد استخدام سمة taskAffinity لتعيين أوجه ارتباط مختلفة للأنشطة المرتبطة بكل "تطبيق".

مسح المكدس الخلفي

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

هناك بعض سمات النشاط التي يمكنك استخدامها لتعديل هذا السلوك:


alwaysRetainTaskState

إذا تم تعيين هذه السمة إلى "true" في النشاط الجذر للمهمة، السلوك الافتراضي الذي تم وصفه للتو لا يحدث. المهمة تحتفظ بجميع الأنشطة في كومة حتى بعد فترة طويلة.
clearTaskOnLaunch
إذا تم تعيين هذه السمة إلى "true" في النشاط الجذر للمهمة، يتم مسح المكدس لأسفل إلى النشاط الجذر كلما يترك المستخدم المهمة ويعود إليها. وبعبارة أخرى، هو عكس alwaysRetainTaskState . يعود المستخدم دائما إلى المهمة في حالته الأولية، حتى بعد مغادرة المهمة للحظة واحدة فقط.
finishOnTaskLaunch
هذه السمة تشبه clearTaskOnLaunch ، ولكنها تعمل على نشاط واحد، وليس مهمة بأكملها. ويمكن أيضا أن يسبب أي نشاط للذهاب بعيدا، بما في ذلك النشاط الجذر. عند تعيينه إلى "true" ، يظل النشاط جزءا من المهمة فقط للدورة الحالية. إذا كان المستخدم يترك ثم يعود إلى المهمة، لم يعد موجودا.
بدء مهمة
يمكنك إعداد نشاط كنقطة دخول لمهمة من خلال إعطائها مرشح نية مع "android.intent.action.MAIN" كإجراء المحدد و "android.intent.category.LAUNCHER" كفئة محددة. فمثلا:
<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...

</activity>



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

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


بالنسبة إلى الحالات التي لا تريد فيها أن يتمكن المستخدم من العودة إلى أحد الأنشطة، قم بتعيين نهاية العنصر <activity> finishOnTaskLaunch إلى "true" finishOnTaskLaunch "true" (راجع مسح حزمة النسخ الخلفي ).



مزيد من المعلومات حول كيفية تمثيل المهام والنشاطات وإدارتها في شاشة نظرة عامة متوفرة في الشاشة الأخيرة .

العمليات ودورة حياة التطبيق



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


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


من المهم أن يفهم مطوري التطبيقات كيف تؤثر مكونات التطبيقات المختلفة (على وجه الخصوص Activity Service BroadcastReceiver ) على عمر عملية التطبيق. عدم استخدام هذه المكونات بشكل صحيح يمكن أن يؤدي إلى نظام قتل عملية التطبيق في حين أنها تقوم بعمل مهم.


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


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


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

يتم تشغيل Activity في الجزء العلوي من الشاشة أن المستخدم يتفاعل مع (تم استدعاء الأسلوب onResume() ).
أنه يحتوي على BroadcastReceiver التي تعمل حاليا BroadcastReceiver.onReceive() طريقة BroadcastReceiver.onReceive() قيد التنفيذ).
لديه Service تعمل حاليا على تنفيذ التعليمات البرمجية في إحدى عمليات Service.onCreate() Service.onStart() أو Service.onDestroy() أو Service.onDestroy() ).
لن يكون هناك سوى عدد قليل من هذه العمليات في النظام، وهذه سوف يقتل فقط كملجأ أخير إذا كانت الذاكرة منخفضة جدا أنه حتى هذه العمليات يمكن أن تستمر في تشغيل. عموما، عند هذه النقطة، وقد وصل الجهاز دولة ترحيل الذاكرة، لذلك مطلوب هذا الإجراء من أجل الحفاظ على واجهة المستخدم تستجيب.

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

يقوم بتشغيل Activity مرئي للمستخدم على الشاشة ولكن ليس في المقدمة (تم استدعاء أسلوب onPause() ). قد يحدث هذا، على سبيل المثال، إذا تم عرض النشاط الأمامي كمحاورة تسمح بعرض النشاط السابق خلفه.
لديها Service تعمل كخدمة مقدمة، من خلال Service.startForeground() (والتي تطلب من النظام التعامل مع الخدمة على أنها شيء يدركه المستخدم، أو مرئيا له بشكل أساسي).
وهي تستضيف خدمة يستخدمها النظام لميزة معينة يدركها المستخدم، مثل خلفية حية، وخدمة أسلوب الإدخال، وما إلى ذلك.
عدد هذه العمليات التي تعمل في النظام هو أقل تقييدا ​​من العمليات الأمامية، ولكن لا تزال تسيطر نسبيا. وتعتبر هذه العمليات مهمة للغاية ولن تقتل إلا إذا كان ذلك مطلوبا للحفاظ على جميع العمليات الأمامية قيد التشغيل.
عملية خدمة واحد يحمل Service التي تم بدء startService() مع الأسلوب startService() . على الرغم من أن هذه العمليات غير مرئية مباشرة للمستخدم، إلا أنها تقوم عموما بالأشياء التي يهتم بها المستخدم (مثل تحميل بيانات الشبكة الخلفية أو تنزيلها)، وبالتالي فإن النظام سيبقي دائما هذه العمليات قيد التشغيل ما لم تكن هناك ذاكرة كافية للاحتفاظ بجميع الأمامية والعمليات المرئية.
قد يتم تخفيض الخدمات التي تم تشغيلها لفترة طويلة (مثل 30 دقيقة أو أكثر) من حيث الأهمية للسماح لعملية إسقاطها إلى قائمة لرو المخزنة مؤقتا الموضحة أدناه. وهذا يساعد على تجنب المواقف حيث خدمات تشغيل طويلة جدا مع تسرب الذاكرة أو مشاكل أخرى تستهلك الكثير من ذاكرة الوصول العشوائي أنها تمنع النظام من الاستخدام الفعال للعمليات المخزنة مؤقتا.
عملية المخزنة مؤقتا هي التي ليست في حاجة حاليا، وبالتالي فإن النظام هو حر لقتل كما هو مطلوب عندما تكون هناك حاجة الذاكرة في مكان آخر. في نظام يتصرف عادة، وهذه هي العمليات الوحيدة التي تنطوي على إدارة الذاكرة: نظام تشغيل جيد سيكون لها العديد من العمليات المخزنة مؤقتا المتاحة دائما (للتحول أكثر كفاءة بين التطبيقات) وقتل بانتظام أقدم منها حسب الحاجة. فقط في الحالات الحرجة جدا (وغير القابلة للتصرف) سوف النظام الحصول على نقطة حيث يتم قتل جميع العمليات المخزنة مؤقتا ويجب أن تبدأ في قتل عمليات الخدمة.
غالبا ما تحتوي هذه العمليات على مثيلات Activity أو أكثر غير مرئية حاليا للمستخدم (تم استدعاء الأسلوب onStop() وإعادته). شريطة أن تنفذ دورة حياتها النشاط بشكل صحيح (انظر Activity لمزيد من التفاصيل)، عندما يقتل النظام هذه العمليات أنها لن تؤثر على تجربة المستخدم عند العودة إلى هذا التطبيق: فإنه يمكن استعادة الدولة المحفوظة سابقا عند إعادة إنشاء النشاط المرتبط في عملية جديدة.
يتم الاحتفاظ بهذه العمليات في قائمة لرو شبه الزائفة، حيث العملية الأخيرة على القائمة هي الأولى التي قتلت لاستعادة الذاكرة. السياسة الدقيقة للترتيب على هذه القائمة هي تفاصيل تنفيذ المنصة، ولكن بشكل عام أنها ستحاول الحفاظ على عمليات أكثر فائدة (واحد استضافة التطبيق المنزل المستخدم، وآخر نشاط رأوا، الخ) قبل أنواع أخرى من العمليات. ويمكن أيضا تطبيق سياسات أخرى لعمليات القتل: حدود صلبة على عدد العمليات المسموح بها، وحدود على مقدار الوقت الذي يمكن أن تبقى فيه العملية مخبأة مؤقتا، وما إلى ذلك.
وعند اتخاذ قرار بشأن كيفية تصنيف عملية ما، سيعتمد النظام على قراره بشأن أهم مستوى وجد بين جميع العناصر النشطة حاليا في العملية. راجع وثائق Activity Service و BroadcastReceiver لمزيد من التفاصيل حول كيفية مساهمة كل من هذه المكونات في دورة الحياة الإجمالية للعملية. وتصف الوثائق الخاصة بكل فئة من هذه الفئات بمزيد من التفصيل كيفية تأثيرها على دورة الحياة العامة لتطبيقها.

ويمكن أيضا زيادة أولوية العملية استنادا إلى التبعيات الأخرى التي تتطلبها العملية. على سبيل المثال، إذا كانت العملية (أ) مرتبطة Service مع Context.BIND_AUTO_CREATE أو كانت تستخدم ContentProvider في العملية B، فإن معالجة تصنيف B ستكون دائما على الأقل بنفس أهمية العملية A.




بارسيلابلز والباقات

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

ملاحظة: Parcel ليست آلية التسلسل العام للأغراض، ويجب أن لا تخزين أي بيانات Parcel على القرص أو إرسالها عبر الشبكة.


إرسال البيانات بين الأنشطة

عندما ينشئ التطبيق كائن Intent لاستخدامها في startActivity(android.content.Intent) في بدء نشاط جديد، التطبيق يمكن أن تمر في المعلمات باستخدام الأسلوب putExtra(java.lang.String, java.lang.String) .


يعرض مقتطف الشفرة التالي مثالا على كيفية تنفيذ هذه العملية.

Intent intent = new Intent(this, MyActivity.class);

intent.putExtra("media_id", "a1b2c3");
...

startActivity(intent);

الطرود نظام التشغيل Bundle الأساسية من القصد. ثم، أوس يخلق النشاط الجديد، الامم المتحدة الطرود البيانات، ويمر النية إلى النشاط الجديد.


نوصي باستخدام فئة Bundle لتعيين الأوليات المعروفة لنظام التشغيل على الكائنات Intent . فئة Bundle هي الأمثل للغاية لتجميع و أونمارشالينغ باستخدام الطرود.


في بعض الحالات، قد تحتاج إلى آلية لإرسال كائنات مركبة أو معقدة عبر الأنشطة. في مثل هذه الحالات، يجب أن فئة مخصصة تنفيذ بارسيلابل، وتوفير writeToParcel(android.os.Parcel, int) المناسبة writeToParcel(android.os.Parcel, int) الأسلوب. يجب أن توفر أيضا حقل غير فارغ يسمى Parcelable.Creator الذي يقوم بتنفيذ واجهة Parcelable.Creator ، الذي createFromParcel() طريقة createFromParcel() لتحويل Parcel إلى الكائن الحالي. لمزيد من المعلومات، راجع الوثائق المرجعية للكائن Parcelable .


عند إرسال البيانات عبر نية، يجب أن تكون حذرا للحد من حجم البيانات إلى بضعة كيلوبايت. إرسال الكثير من البيانات يمكن أن يسبب النظام لرمي استثناء ترانزاكتيونتيولارجيكسسيبتيون.


إرسال البيانات بين العمليات

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

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


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


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


ملاحظة: في أندرويد 7.0 (أبي ليفيل 24) وأعلى، يقوم النظام بإلقاء ترانزاكتيونتيولارجيكسسيبتيون كاستثناء وقت التشغيل. في إصدارات أقل من الروبوت، النظام يظهر فقط تحذيرا في لوغكات.





شاشة حديثة



في هذه الوثيقة

إضافة المهام إلى الشاشة الأخيرة
استخدام العلم النية لإضافة مهمة
استخدام السمة أكتيفيتي لإضافة مهمة
إزالة المهام
استخدام فئة أبتاسك لإزالة المهام
الاحتفاظ المهام الانتهاء
الطبقات الرئيسية
ActivityManager.AppTask
Intent
عينة من الرموز
التطبيقات التي تركز على المستند

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



الشكل 1. شاشة ريسينتس التي تعرض ثلاث مستندات من غوغل دريف، تمثل كل منها مهمة منفصلة.







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






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


قبل الروبوت 5.0 مقابل وجهات النظر السابقة من الشاشة الحديثة

الشكل 2. الشاشة الأخيرة في الروبوت 5.0 وأعلى (يسار)، وفي إصدارات أقل من الروبوت 5.0 (يمين).

عادة يجب أن تسمح للنظام بتحديد كيفية تمثيل المهام والأنشطة في الشاشة الأخيرة ، ولا تحتاج إلى تعديل هذا السلوك. ومع ذلك، يمكن لتطبيقك تحديد كيفية ومتى تظهر الأنشطة في الشاشة الأخيرة . تتيح لك فئة ActivityManager.AppTask إدارة المهام، وتتيح لك أعلام الأنشطة الخاصة بفئة Intent تحديد متى تتم إضافة نشاط أو إزالته من شاشة ريسينتس . أيضا، تسمح لك سمات <activity> بتعيين السلوك في البيان.


لمزيد من المعلومات حول النموذج المستند إلى المستند، اطلع على مشاركة المدونة هذه .


إضافة المهام إلى الشاشة الأخيرة

استخدام أعلام فئة Intent لإضافة مهمة يتيح مزيدا من التحكم في متى وكيف يتم فتح المستند أو إعادة فتحه في الشاشة الأخيرة . عند استخدام سمات <activity> يمكنك الاختيار بين فتح المستند دائما في مهمة جديدة أو إعادة استخدام مهمة موجودة للمستند.

استخدام العلم النية لإضافة مهمة

عند إنشاء مستند جديد لنشاطك، استدعاء الأسلوب startActivity() ، ويمرر إليه النية التي تطلق النشاط. لإدراج فاصل منطقي بحيث يتعامل النظام مع نشاطك كمهمة جديدة في شاشة FLAG_ACTIVITY_NEW_DOCUMENT ، مرر علامة FLAG_ACTIVITY_NEW_DOCUMENT في أسلوب addFlags() Intent التي تطلق النشاط.

ملاحظة: تحل العلامة FLAG_ACTIVITY_NEW_DOCUMENT محل علامة FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET ، التي تم إيقافها اعتبارا من أندرويد 5.0 (مستوى واجهة برمجة التطبيقات (أبي)).


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



DocumentCentricActivity.java

public void createNewDocument(View view) {
      final Intent newDocumentIntent = newDocumentIntent();
      if (useMultipleTasks) {
          newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
      }
      startActivity(newDocumentIntent);
  }

  private Intent newDocumentIntent() {

      boolean useMultipleTasks = mCheckbox.isChecked();
      final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
      newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
      newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
      return newDocumentIntent;
  }

  private static int incrementAndGet() {

      Log.d(TAG, "incrementAndGet(): " + mDocumentCounter);
      return mDocumentCounter++;
  }

}
ملاحظة: يجب أن تحتوي الأنشطة التي تم إطلاقها باستخدام علامة FLAG_ACTIVITY_NEW_DOCUMENT قيمة السمة android:launchMode="standard" (القيمة الافتراضية) المحددة في البيان.

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



NewDocumentActivity.java


@Override

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_new_document);
    mDocumentCount = getIntent()
            .getIntExtra(DocumentCentricActivity.KEY_EXTRA_NEW_DOCUMENT_COUNTER, 0);
    mDocumentCounterTextView = (TextView) findViewById(
            R.id.hello_new_document_text_view);
    setDocumentCounterText(R.string.hello_new_document_counter);
}

@Override

protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    /* If FLAG_ACTIVITY_MULTIPLE_TASK has not been used, this activity
    is reused to create a new document.
     */
    setDocumentCounterText(R.string.reusing_document_counter);

}
استخدام السمة أكتيفيتي لإضافة مهمة
يمكن أن يحدد النشاط أيضا في بيانه أنه يبدأ دائما في مهمة جديدة باستخدام السمة <activity> ، android:documentLaunchMode . تحتوي هذه السمة على أربع قيم تنتج التأثيرات التالية عندما يفتح المستخدم مستندا مع التطبيق:

" intoExisting "

ويعيد النشاط استخدام مهمة قائمة في الوثيقة. هذا هو نفس وضع علامة FLAG_ACTIVITY_NEW_DOCUMENT بدون وضع علامة FLAG_ACTIVITY_MULTIPLE_TASK ، كما هو موضح في استخدام علامة FLAG_ACTIVITY_MULTIPLE_TASK لإضافة مهمة ، أعلاه.
" always "
يؤدي النشاط إلى إنشاء مهمة جديدة للوثيقة، حتى إذا تم فتح المستند بالفعل. استخدام هذه القيمة هو نفس إعداد كل من FLAG_ACTIVITY_NEW_DOCUMENT و FLAG_ACTIVITY_MULTIPLE_TASK الأعلام.
" none "
لا يؤدي النشاط إلى إنشاء مهمة جديدة للوثيقة. شاشة حديثي يتعامل مع النشاط كما سيكون افتراضيا: فإنه يعرض مهمة واحدة للتطبيق، الذي يستأنف من أي نشاط آخر استدعاء المستخدم.
" never "
لا يؤدي النشاط إلى إنشاء مهمة جديدة للوثيقة. FLAG_ACTIVITY_NEW_DOCUMENT تعيين هذه القيمة إلى تجاوز سلوك FLAG_ACTIVITY_NEW_DOCUMENT و FLAG_ACTIVITY_MULTIPLE_TASK الأعلام، إذا تم تعيين أي منهما في النية، كما تعرض الشاشة الأخيرة مهمة واحدة للتطبيق، والتي تستأنف من أي نشاط آخر استدعيه المستخدم.
ملاحظة: بالنسبة للقيم الأخرى بخلاف none never يجب تعريف النشاط never مع launchMode="standard" . إذا لم يتم تحديد هذه السمة، documentLaunchMode="none" استخدام documentLaunchMode="none" .

إزالة المهام

بشكل افتراضي، تتم إزالة مهمة المستند تلقائيا من شاشة ريسينتس عند انتهاء نشاطها. يمكنك تجاوز هذا السلوك مع فئة ActivityManager.AppTask ، مع علم Intent ، أو مع سمة <activity> .

يمكنك دائما استبعاد مهمة من شاشة ريسنتس بالكامل عن طريق تعيين السمة <activity> ، android:excludeFromRecents إلى android:excludeFromRecents .


يمكنك تعيين الحد الأقصى لعدد المهام التي يمكن أن android:maxRecents تطبيقك في شاشة " الأخيرة" من خلال تعيين السمة <activity> android:maxRecents إلى قيمة عدد صحيح. الافتراضي هو 16. عند الوصول إلى الحد الأقصى لعدد المهام، تتم إزالة المهمة الأقل استخداما مؤخرا من شاشة ريسينتس . android:maxRecents أقصى قيمة هو 50 (25 على أجهزة الذاكرة منخفضة). القيم أقل من 1 غير صالحة.


استخدام فئة أبتاسك لإزالة المهام

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


NewDocumentActivity.java

public void onRemoveFromRecents(View view) {
    // The document is no longer needed; remove its task.
    finishAndRemoveTask();

}

ملاحظة: يؤدي استخدام طريقة finishAndRemoveTask() تجاوز استخدام العلامة FLAG_ACTIVITY_RETAIN_IN_RECENTS ، التي تمت مناقشتها أدناه.


الاحتفاظ المهام الانتهاء

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


DocumentCentricActivity.java

private Intent newDocumentIntent() {

    final Intent newDocumentIntent = new Intent(this, NewDocumentActivity.class);
    newDocumentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
      android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
    newDocumentIntent.putExtra(KEY_EXTRA_NEW_DOCUMENT_COUNTER, incrementAndGet());
    return newDocumentIntent;

}

ولتحقيق نفس التأثير، android:autoRemoveFromRecents السمة <activity> android:autoRemoveFromRecents إلى android:autoRemoveFromRecents . القيمة الافتراضية هي true لأنشطة المستند، و false للأنشطة العادية. يؤدي استخدام هذه السمة إلى تجاوز العلامة FLAG_ACTIVITY_RETAIN_IN_RECENTS تمت مناقشتها سابقا.

ليست هناك تعليقات:

إرسال تعليق

للوضع الليلي في التطبيق DayNight

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