مقدّمة عن الأنشطة

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

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

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

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

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

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

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

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

إعداد البيان

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

تعريف الأنشطة

لتعريف نشاطك، افتح ملف البيان وأضِف عنصر <activity> كعنصر فرعي من العنصر <application>. على سبيل المثال:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

السمة المطلوبة الوحيدة لهذا العنصر هي android:name، التي تحدّد اسم فئة النشاط. يمكنك أيضًا إضافة سمات تحدّد خصائص النشاط، مثل التصنيف أو الرمز أو مظهر واجهة المستخدم. لمزيد من المعلومات عن هذه السمات والسمات الأخرى، يُرجى الاطّلاع على <activity> عنصر مرجع المستندات.

تعريف فلاتر الأهداف

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

يمكنك الاستفادة من هذه الميزة من خلال تعريف سمة <intent-filter> في عنصر <activity>. يتضمّن تعريف هذا العنصر عنصر <action>، وعنصر <category> و/أو عنصر <data> اختياريًا. تتحد هذه العناصر لتحديد نوع الهدف الذي يمكن أن يستجيب له نشاطك. على سبيل المثال، يوضّح مقتطف الرمز التالي كيفية إعداد نشاط يرسل بيانات نصية ورسائل إلكترونية ويتلقّى طلبات من أنشطة أخرى لإجراء ذلك:

<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>
   <intent-filter>
        <action android:name="android.intent.action.SENDTO" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="mailto" />
    </intent-filter>
</activity>

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

fun composeEmail(addresses: Array<String>, subject: String) {
    val intent = Intent(Intent.ACTION_SENDTO).apply {
        data = Uri.parse("mailto:") // Only email apps handle this.
        putExtra(Intent.EXTRA_EMAIL, addresses)
        putExtra(Intent.EXTRA_SUBJECT, subject)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

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

التعامل مع الأهداف الواردة

يوضّح المثال التالي نمطًا لإدارة دورة حياة النشاط أثناء التعامل مع أنواع متعددة من الأهداف: مشاركة نص واحد وصورة واحدة ومصفوفات صور متعددة. من خلال توجيه هذه الإدخالات المتنوّعة من خلال دالة مركزية handleIntent، يضمن ذلك تحليل الإجراءَين ACTION_SEND و ACTION_SEND_MULTIPLE بشكلٍ صحيح وتفويضهما إلى ViewModel لتحديث واجهة المستخدم التفاعلية.

class ExampleActivity : ComponentActivity() {
  private val viewModel: MyViewModel by viewModels()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    handleIntent(intent)
    setContent {
      ComposeApp(viewModel)
    }
  }

  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleIntent(intent)
  }

  private fun handleIntent(intent: Intent?) {
    when (intent?.action) {
      Intent.ACTION_SEND -> {
        if ("text/plain" == intent.type) {
          intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
            viewModel.handleText(it) // Update UI to reflect text being shared
          }
        } else if (intent.type?.startsWith("image/") == true) {
          (intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java))?.let {
            viewModel.handleImage(it) // Update UI to reflect image being shared
          }
        }
      }

      Intent.ACTION_SEND_MULTIPLE -> {
          if (intent.type?.startsWith("image/") == true) {
              intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let {
                  viewModel.handleMultipleImages(it) // Update UI to reflect multiple images being shared
              }
          } else {
              // Handle other types
          }
      }

      else -> {
          // Handle other intents
      }
    }
  }
}

تضمين الأذونات في نماذج البيان

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

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

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

/>

بعد ذلك، لكي يُسمح لتطبيقك باستدعاء SocialApp، يجب أن يتطابق مع مجموعة الأذونات التي تم ضبطها في بيان SocialApp:

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

لمزيد من المعلومات عن الأذونات والأمان بشكلٍ عام، يُرجى الاطّلاع على قائمة التحقّق من الأمان.

إدارة مراحل النشاط

يمرّ النشاط بعدد من الحالات خلال دورة حياته. يمكنك استخدام سلسلة من عمليات ردّ الاتصال للتعامل مع عمليات الانتقال بين الحالات. تقدّم الأقسام التالية عمليات ردّ الاتصال هذه. في تطبيق Compose، لا يُنصح بالربط مباشرةً بعمليات ردّ الاتصال هذه. بدلاً من ذلك، استخدِم واجهة برمجة تطبيقات دورة الحياة لمراقبة تغييرات الحالة. لمزيد من المعلومات، يُرجى الاطّلاع على دمج مراحل النشاط مع Compose.

onCreate

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

في تطبيق Compose، استخدِم عملية ردّ الاتصال هذه لإعداد العنصر القابل للإنشاء المضيف باستخدام setContent، كما هو موضّح أدناه:

class MyActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text(text = stringResource(id = R.string.greeting))
        }
    }
}

عند انتهاء onCreate، تكون عملية ردّ الاتصال التالية دائمًا onStart.

onStart

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

onResume

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

تتبع عملية ردّ الاتصال onPause دائمًا عملية onResume.

onPause

يستدعي النظام onPause عندما يفقد النشاط التركيز وينتقل إلى الحالة Paused. تحدث هذه الحالة عندما ينقر المستخدم مثلاً على الزر "رجوع" أو "التطبيقات الحديثة". عندما يستدعي النظام onPause لنشاطك، يعني ذلك من الناحية الفنية أنّ نشاطك لا يزال مرئيًا جزئيًا، ولكن في معظم الأحيان يشير ذلك إلى أنّ المستخدم يغادر النشاط، وسينتقل النشاط قريبًا إلى الحالة Stopped أو Resumed.

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

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

بعد انتهاء تنفيذ onPause، تكون عملية ردّ الاتصال التالية إما onStop أو onResume، استنادًا إلى ما يحدث بعد انتقال النشاط إلى الحالة Paused.

onStop

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

عملية ردّ الاتصال التالية التي يستدعيها النظام هي إما onRestart، إذا كان النشاط سيعود للتفاعل مع المستخدم، أو onDestroy إذا كان هذا النشاط سينتهي تمامًا.

onRestart

يستدعي النظام عملية ردّ الاتصال هذه عندما يكون النشاط في الحالة Stopped على وشك إعادة التشغيل. onRestart تستعيد حالة النشاط من الوقت الذي تم فيه إيقافه.

تتبع عملية ردّ الاتصال هذه دائمًا عملية onStart.

onDestroy

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

عملية ردّ الاتصال هذه هي الأخيرة التي يتلقّاها النشاط. onDestroy يتم تنفيذه عادةً لضمان تحرير جميع موارد النشاط عند تدمير النشاط أو العملية التي تحتوي عليه.

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