أساسيات التطبيقات

نقل بيانات تطبيق Google Play الذي يعود تاريخه إلى عقدَين من الزمن إلى Jetpack Compose

سماعات

  • كيريل غروتشنيكوف

    مهندس برمجيات

  • جون بوكينوجين

    مهندس برمجيات

لمحة

لمحة عن المحاضرة

هذا العام، أصبح Android رسميًا يعتمد على Compose أولاً لإنشاء جميع واجهات المستخدم، وتم وضع طرق العرض القديمة في وضع الصيانة. بالنسبة إلى Google Play، بدأت هذه الرحلة في عام 2020. على مدار ما يقرب من عقدين من الزمن، ومع مليارات المستخدمين، تم تحقيق عملية الانتقال إلى Jetpack Compose من خلال أفضل الممارسات المُثبتة والتعاون الوثيق مع فريق Compose الأساسي والتطوير المستمر للأدوات.

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

ملخّص

  • نقل Google Play ‏97% من مرّات ظهور المستخدمين إلى شاشات Compose فقط على مدار ست سنوات. وشهدت الصفحات الرئيسية أيضًا تحسّنًا بنسبة %30 في معدّل التقطّع خلال آخر 14 شهرًا.
  • يحدّ الاعتماد التدريجي من المخاطر التي تواجهها الأنشطة التجارية في قواعد الرموز البرمجية الكبيرة. يمكن للفِرق التعرّف على الشاشات ذات عدد الزيارات المنخفض أولاً، ثم الانتقال إلى استضافة ComposeView مباشرةً في جذر النشاط.
  • يعمل التصميم الديناميكي بالكامل في الرمز البرمجي باستخدام تراكبات MaterialTheme ومكتبة Material Color Utilities. يؤدي ذلك إلى تجنُّب عمليات تفكيك الأنشطة، على الرغم من أنّ إنشاء أنظمة الألوان في وقت الإنشاء يساعد في الحدّ من وقت الاستجابة أثناء التشغيل.
  • يؤدي تدفق البيانات أحادي الاتجاه وواجهة المستخدم التعريفية إلى تبسيط البنية وإزالة عدة أنواع من حالات السباق. أدى تشغيل مصادر البيانات وتحويلات واجهة المستخدم بالتوازي إلى تحسين وقت استجابة التحميل في Google Play بعشرات المللي ثانية.
  • تفرض عمليات التحقّق الآلية من Lint قواعد جودة الرموز البرمجية ونظام التصميم. ويستخدمها Play لحظر الألوان المرمّزة بشكل ثابت والإبلاغ عن المشاكل المحتملة في الأداء، مثل BoxWithConstraints.

Gemini Notebook

المواضيع

  • jetpack-compose
  • نقل البيانات
  • أداء
  • تصنيف الكلمات الرئيسية حسب الموضوع
  • unidirectional-data-flow
  • lint-rules
  • developer-velocity

النص

تنزيل النص

مقدّمة عن "متجر Google Play" واعتماده

  • مرحبًا

  • اسمي جمال.

  • أنا من فريق "متجر Google Play".

  • هذا زميلي "كيريل".

  • سنتحدّث اليوم عن كيفية نقل الكثير من الرموز البرمجية من نظام View وFragment إلى Compose.

  • لنبدأ

  • فكيف تمّت عملية الاعتماد وما هو نطاقها؟

  • بالنسبة إلى قاعدة الرموز البرمجية لتطبيقنا، فقد تطوّرت بشكل طبيعي منذ عام 2007 تقريبًا.

  • لدينا بضعة ملايين من أسطر الرموز البرمجية للإنتاج، و200 شاشة، و500 مكوّن فريد لواجهة المستخدم يتم استخدامها في العديد من هذه الشاشات المختلفة.

  • في عام 2020، لاحظنا أنّ سرعة المطوّرين وموثوقية التطبيق وأداءه لم تكن تحقّق الأهداف التي أردناها.

  • لذلك، قرّرنا استخدام حزمة تكنولوجيا حديثة لواجهة المستخدم.

  • قيّمنا مجموعة من المكتبات المختلفة.

  • وكان لدينا أيضًا بعض الأصدقاء في AndroidX يتحدثون إلينا عن Compose في ذلك الوقت، وقررنا اعتماد Compose وأن نصبح أول شريك رئيسي لـ Compose.

  • كيف سار الأمر؟

  • بعد ست سنوات، أصبح لدينا الآن %97 من مرّات ظهور المستخدمين داخل تطبيق "متجر Google Play" على الشاشات التي تستخدم Compose فقط.

  • عذرًا، لقد انتقلت جميع عمليات تطوير الهواتف والشاشات الكبيرة إلى Compose-only منذ عام 2020.

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

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

  • وقد استخدموا حزمة اختبارية قوية وشاملة ساعدتنا في اعتماد إصدارات جديدة من Compose مرتين في الأسبوع.

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

  • بالحديث عن الأداء على وجه الخصوص، قدّم Compose أداءً سلسًا ومستمرًا لتطبيقنا على جميع شاشاتنا الرئيسية.

  • هذه هي صفحة نتائج البحث، والصفحة الرئيسية، وصفحة التفاصيل.

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

  • لذلك، شهدنا تحسّنًا بنسبة %30 خلال آخر 14 شهرًا.

خطة نقل البيانات

  • ولكن كيف وصلنا إلى هنا؟

  • هذا ما سنتحدث عنه اليوم.

  • لنتحدّث الآن عن خطة نقل البيانات.

  • لذلك، اتّبع فريق Google Play نهجًا متعدد الخطوات.

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

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

  • لذا، سأسمّيها: الزحف والمشي والهرولة والجري.

  • لذلك، كانت مرحلة الزحف بالنسبة إلينا تهدف إلى التعرّف على Compose.

  • بدأنا بصفحة تسجّل عددًا منخفضًا من الزيارات.

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

  • هدفك الرئيسي هو التعرّف على مكتبة Compose.

  • لذا، يمكن أن يكون هذا معتادًا على الصفوف والأعمدة والنصوص والصور وكل هذه الأنواع من الأشياء.

  • بعد ذلك، عليك البدء في جلب البنية الأساسية لتطبيقك وفهم كيفية عملها في Compose.

  • قد يكون ذلك تسجيل مرات الظهور أو تسجيل النقرات أو المظاهر، وكنا نجدد تحميل البيانات في الوقت نفسه.

  • لذا، كل هذه الأشياء.

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

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

  • بالنسبة إلينا، كان ذلك يعني استخدام مكوّن أصغر على شاشة تشهد عددًا كبيرًا من الزيارات وتقييم شكل عملية النقل هذه.

  • ننصحك باختيار عنصر في RecyclerView، حتى تتمكّن من فهم أي مشاكل في التوافق بين نظامَي View وCompose، والاطّلاع أيضًا على قياس الأداء والبطء أثناء العملية.

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

  • من الأمور التي يجب الانتباه إليها وتوقُّعها في هذا المجال هي زيادة طفيفة في معدّل البطء ووقت الاستجابة، وذلك لأنّك تشغّل الآن حزمتَين.

  • لديك حزمة عرض كلها في Compose وأخرى في Views.

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

  • ولكن مع استخدامك المزيد من ميزات Compose، ستختفي هذه المشكلة.

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

  • لذا بعد المشي، ننتقل إلى الركض.

  • هذا بعد أن نصبح مرتاحين جدًا.

  • بدلاً من إجراء مكوّن واحد على صفحة ذات عدد زيارات مرتفع، ما عليك سوى إجراء الصفحة ذات عدد الزيارات المرتفع بالكامل.

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

  • لقد جعلنا Fragment يعرض ComposeView نفسه.

  • لذا، يمكنك توقُّع تحسين وقت الاستجابة والتقطُّع.

  • لن تواجه الكثير من مشاكل الذاكرة وتحميل الفئات التي كنت أتحدث عنها.

  • ويُجري Compose نفسه أيضًا بعض مستويات التخزين المؤقت على مستوى ComposeView.

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

  • بعد ذلك، انتقلنا إلى الركض.

  • هنا تبدأون بالتركيز على كل التفاصيل.

  • بعد أن تحصل على غالبية زياراتك من تطبيقك على Compose، انتقلنا إلى مستوى أعلى.

  • لذلك، فوق الشاشات، لدينا النشاط.

  • لذا، انقل ComposeView إلى جذر النشاط.

  • وستبدو الكثير من التعليمات البرمجية متشابهة نسبيًا.

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

  • ولكن بدلاً من إجراء معاملات Fragment، يتم استدعاء دالة مركّبة.

  • ويمكنك إجراء ذلك بالإضافة إلى مكتبة Nav2 أو مكتبة Nav3، أيًا كان اختيارك.

  • بالنسبة إلينا، لم ننقل جميع شاشاتنا.

  • لقد ذكرت أنّ لدينا الكثير منها.

  • لذلك، أنشأنا ميزة توافق Fragment التي تتيح لك استخدام شاشة مستندة إلى Fragment والاستفادة من برامج تضمين AndroidFragment في Compose لإجراء ذلك.

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

  • ولكن يمكنك أيضًا الحصول على إمكانات جديدة.

  • لدينا مثال على ذلك على اليمين في ملف GIF هذا حيث يمكنك إجراء انتقالات العناصر المشتركة بين الشاشات.

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

  • يمكنك أيضًا الاستفادة من مرونة الرسوم المتحركة في Compose أثناء إجراء عملية الانتقال بالكامل.

  • والآن، سأترك الكلام لـ "كيريل" ليتحدّث عن بعض الإمكانات الإضافية.

المظاهر والأداء

  • شكرًا، جمال.

  • أريد أن أتحدث قليلاً عن موضوع قريب وعزيز على قلبي، وهو تصميم المظاهر والأنماط لتطبيقات Android، وهو أمر أفعله منذ فترة طويلة.

  • في عالم View، كان هناك رمز Java وبعد ذلك بقليل رمز Kotlin، ثم كانت هناك موارد X-- XML، وموارد مثل الألوان والسلاسل والأبعاد والتخطيطات والسمات والأنماط.

  • وكانت طريقة عملها هي أنّه يتم تجميع كل موارد XML هذه في جدول موارد مضمّن في حزمة APK، وكان ثابتًا إلى حد كبير.

  • هناك واجهة برمجة تطبيقات Resources.Theme.applyStyle يمكنك استخدامها ديناميكيًا أثناء التشغيل لتطبيق نمط مخصّص على أعلى التسلسل الهرمي لواجهة المستخدم.

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

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

  • كان من الصعب نوعًا ما إنشاء نموذج ذهني مناسب للتسلسل الهرمي للأنماط في عالم XML.

  • وأخيرًا، لم يكن هناك عرض موحّد واحد في استوديو Android أو أي أداة للمطوّرين أخرى تسمح لك بسد الفجوة بين عالم Java وعالم الرموز وعالم تنسيق XML.

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

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

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

  • نطبّق تراكب تخصيص التصميم المتعدد الأبعاد هذا مع نظام ألوان مخصّص تم إنشاؤه بواسطة مكتبة Material Color Utilities، المتاحة على GitHub لتستخدمها.

  • نمرر نوعًا من هذا اللون البني والأصفر والذهبي كبذرة، ويولد الطيف الكامل لرموز ألوان المواد، الأساسي على الأساسي، والثانوي على الثانوي، والذي نستخدمه بعد ذلك داخل تنفيذ هذه البطاقة.

  • ويتيح ذلك لمطوّري برامج Android الاستفادة من ميزة "الألوان الديناميكية" بالكامل.

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

  • وداخليًا، يتم إرفاق هذه العناصر كمتغيرات CompositionLocal بعُقد واجهة المستخدم المحدّدة في التسلسل الهرمي، حيث تختار تطبيقها.

  • اعتبارات الأداء: لا يمكن إنشاء نظام ألوان كامل باستخدام مكتبة Material Color Utilities مجانًا.

  • وهذا يتطلّب بعض الموارد الإضافية.

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

  • لذا، أولاً، عليك البدء في قياس مدى تأثير ذلك على الأداء، وثانيًا، يمكنك نقل بعض هذه الأعباء من وقت التشغيل إلى وقت الإنشاء.

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

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

  • لذا، بناءً على عدد ما تستخدمه من هذه، العشرات، المئات، يبدأ في الإضافة.

  • وفي مرحلة ما، قد ترغب في البدء في النظر في تكلفة كل هذه العناصر المحلية المجمعة.

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

  • لدينا هنا أربعة أقسام، والمرئيات نفسها، ولنسمّيها بطاقة الحدث.

  • لدينا هذه الصورة الرئيسية التي تمتد على البطاقة بأكملها، ثم لدينا تصنيف في أعلى اليمين، وزر في أسفل اليسار، وبعض النصوص.

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

  • تنفيذ البطاقة موحّد لجميع هذه البطاقات الأربعة.

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

  • ولن يطرأ أي تغيير آخر.

  • لست بحاجة إلى إلغاء نشاطك وإعادة إنشائه.

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

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

  • والآن، نعود إلى "جون" للانتقال إلى القسم التالي.

توسيع نطاق الموثوقية والسرعة

  • أجل

  • هذا مثال آخر على المرونة التي تحدّث عنها "كيريل".

  • لنتحدّث عن الموثوقية والسرعة.

  • لذلك، يسعى جميع المطوّرين والشركات إلى إنشاء رموز برمجية عالية الجودة بسرعة.

  • لنتعرّف على كيفية مساهمة Compose في تمكين Google Play من تحقيق ذلك.

  • لذا، أولاً وقبل كل شيء، أعلم أنّ المخطّط البياني كبير، ولكنّ بساطة البنية لها فوائد هائلة لجميع مؤلفي الرموز البرمجية والمشرفين عليها، سواء كانوا بشرًا أو وكلاء.

  • لن أتعمّق كثيرًا في هذا الموضوع، ولكن أحد النماذج الذهنية التي تحاول Compose طرحها هو تدفق البيانات أحادي الاتجاه، وقد كان له تأثير كبير على فريقنا.

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

  • يوفّر مصدر البيانات البيانات.

  • وقد يتم تحويل هذه البيانات إلى واجهة مستخدم معيّنة، والتي نخرجها كنموذج واجهة مستخدم.

  • ويمكن لـ Compose بعد ذلك مراقبة ذلك بسهولة من خلال استدعاء سمة قيمة في تلك الحالة.

  • هذا نوع من الأسهم على طول الجانب العلوي من هذا المخطط.

  • وبعد ذلك، تتدفق الأحداث في الاتجاه المعاكس.

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

  • لذلك، يتم تنفيذ كل شيء من خلال هذه الحلقة البسيطة نسبيًا.

  • ومن المزايا التي لاحظناها أنّ هذه الميزة تساعد في تقليل فترة تحسين الأداء.

  • لم يعُد هناك المزيد من الأسئلة مثل أين تحدث كل هذه الاستدعاءات لسلسلة التعليمات الرئيسية أو خارج سلاسل التعليمات الأخرى هذه.

  • ويتبع حلقة عامة واحدة.

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

  • وقد قلّل النموذج الذهني من العديد من المحادثات حول مصادر الحقيقة داخل فريقنا وأزال تمامًا عدة أنواع من حالات السباق.

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

  • وقد أدى ذلك إلى تحسين وقت استجابة التحميل في المتجر بمقدار عشرات الملّي ثانية، أي 50 ملّي ثانية أو ما شابه.

  • كان ذلك رائعًا بالنسبة لنا.

  • بالإضافة إلى تدفق البيانات أحادي الاتجاه، فإنّ الميزة الأخرى المهمة في Compose هي واجهة المستخدم التعريفية.

  • تطرّق "كيريل" إلى هذا الموضوع قليلاً.

  • وقد نالت هذه الميزة إعجاب مطوّري Play أيضًا.

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

  • لدينا مثال على اليسار وهو بسيط إلى حد ما.

    @Composable
    fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
      Row(modifier) {
        Text("20% off sale")
        if (LocalExpts.current.useButtonV2) {
          ButtonV2("Buy", onClick = onClick)
        } else {
          ButtonV1("Buy", onClick = onClick)
        }
      }
    }
  • نحن نغيّر بين تنفيذين للأزرار استنادًا إلى علامة تجريبية.

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

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

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

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

  • لذا، كان ذلك مفيدًا جدًا لنا.

التمهيد لنماذج اللغة الكبيرة

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

  • وأنا متأكد من أنّ الكثير منكم قد جرّبوا ذلك أو نفّذوه باستخدام النموذج اللغوي الكبير المفضّل لديهم.

  • يمكنك أخذ لقطة شاشة مشروحة بالألوان والخطوط وإدخالها، ويمكنه إنشاء صفوف وأعمدة ونصوص وأزرار، ويؤدي مهمة معقولة.

  • ومع ذلك، فإنّ له بعض القيود.

  • وما لاحظناه في Play هو أنّها لا تفهم قاعدة الرموز البرمجية، أليس كذلك؟

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

  • فهي تمنحك فقط ألوانًا وسلاسل غير قابلة للتغيير في البرنامج.

  • ما هو المحتوى الذي يجب أن يكون من الجهاز، وما هو المحتوى الذي يجب أن يأتي من خادم، أو كيف أتأكد من أنه يعمل بشكل جيد في استخدام LazyList وليس مجرد إنشاء عمود ضخم؟

  • لذا، ما فعلناه لمعالجة بعض هذه المشاكل هو إضافة بعض البيانات الوصفية إلى لقطات الشاشة هذه.

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

  • ثم أيضًا توقيع دالة عالي المستوى، حتى تتمكن من إخباره بالمحتوى الديناميكي مقابل الثابت.

  • لذا، ينتهي بك الأمر بشيء مثل ما كان لدينا من قبل، والانتقال إلى ما بعد ذلك.

  • ليس لديّ المربّعات المحيطة هنا لأنّها ستضيف الكثير من التشويش إلى المخطّط البياني.

  • ولكن يمكنك أن ترى تلك الألوان وأسماء الطباعة غير القابلة للتغيير في البرنامج يتم استبدالها بالعنوان الكبير وعلى السطح.

  • لدينا أسماء المكونات مثل رأس البطاقة وشارة الرمز محددة بوضوح.

  • بهذه الطريقة، يمكن العثور على هذه العناصر في قاعدة الرموز البرمجية.

  • بالنسبة إلينا، لدينا الكثير من هذه العناصر التي تأتي من مكتبات التصميم الشائعة أيضًا، والتي سيتحدث عنها "كيريل" بعد قليل.

  • لذلك، لن تضع تصنيفات مخصّصة لكل هذه المنتجات طوال الوقت.

  • ويمكنك إقران ذلك بتوقيع طريقة مثل الذي لدينا في الأسفل، OfferCard، وبعد ذلك يعرف، كما تعلم، أن العنوان، وendDate، والصورة كلها ديناميكية.

  • يجب ألا نستخدم بيانات غير قابلة للتغيير في البرنامج.

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

  • وبذلك، ننشئ الكثير من الرموز البرمجية.

  • سأترك الكلمة الآن لـ "كيريل" ليتحدّث عن كيفية الحفاظ على الجودة.

أتمتة الجودة

  • صحيح؟

  • شكرًا، جمال.

  • لذا، استكمالاً لموضوع النماذج اللغوية الكبيرة والتطوير بمساعدة الوكلاء، سنبدأ أولاً بجانب تصميم تجربة المستخدم.

  • ما تريد فعله هو، أيًا كانت أداة التصميم التي تختارها، ربما Figma، وربما شيء آخر، تريد أن يكون لديك نموذج تمت مشاركته يستخدمه جميع المصممين الذين لديهم رموز ألوان، ورموز طباعة، ورموز شكل من نظام التصميم الذي تختاره.

  • ربما يكون Material.

  • قد يكون نظام التصميم المخصّص لديك.

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

  • حتى يتمكن المصممون من التبديل بسرعة بين هذه المجموعات المختلفة لمعرفة كيفية استجابة مواصفات التصميم الخاصة بهم لذلك.

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

  • وأخيرًا، ما وجدناه مفيدًا جدًا على مستوى Google Play، هو أنّ لدينا، ليس العشرات، بل بضع مئات من المكوّنات والمجموعات والبطاقات والحاويات التي يتم استخدامها على مجموعة متنوعة من الشاشات التي لدينا.

  • ما وجدناه مفيدًا هو تتبُّع كل هذه المعلومات في مكان واحد، وهو ما نسميه كتالوج المكوّنات، ثم تدريب وكيل مخصّص على كتالوج المكوّنات هذا.

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

  • ويقلّل ذلك بشكل كبير من تكاليف التصميم والتنفيذ.

  • في ما يتعلق بالتنفيذ، نعتمد بشكل كبير على قواعد Lint الأساسية والمخصّصة.

  • هناك قاعدتان أساسيتان في Lint أريد الإشارة إليهما، وهما FrequentlyChangingValueDetector التي تساعد في تحديد مصادر عمليات إعادة الإنشاء غير الضرورية، والتي يمكن أن تؤدي إلى وقت استجابة وبطء، والأخرى هي ScaffoldPaddingDetector للإشارة إلى الحالات التي نستخدم فيها الدالة المركّبة Scaffold في Material Compose، ولكن نتجاهل الهوامش الواردة.

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

  • وأخيرًا، BoxWithConstraints، الذي يأتي مع بعض اعتبارات الأداء.

  • قد يستغرق الأمر إطارين لتخطيط كل شيء بشكل صحيح.

  • لا نحظرها تمامًا، ولكننا نضع علامة عليها كتحذير من Lint لكي يعرف المطوّر الذي يعمل على هذه الشاشة المحدّدة أنّه يتّخذ خيارًا محدّدًا لاستخدام BoxWithConstraints، أو ربما يمكنه اختيار استخدام شيء آخر لهذا التنسيق المحدّد.

  • بالنسبة إلى التشغيل الآلي للمظاهر، مرة أخرى، رموز الألوان، ورموز أسلوب الخط، ورموز الأشكال.

  • لدينا قاعدة Lint تحظر استخدام الألوان وأساليب الخطوط المضمّنة في الرمز البرمجي.

  • لدينا قاعدة Lint تضع علامة على استخدام مكوّنات Material 2.

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

  • لدينا قاعدة Lint مخصّصة تمنع المستخدمين من قراءة الألوان من ملفات XML القديمة مثلاً.

  • نريد أن نعتمد على Compose أولاً وفقط للشاشات الجديدة.

  • وتتضمّن الدوال المركّبة للنصوص، خاصةً في نظام التصميم المتعدد الأبعاد، بدائل للنمط واللون.

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

  • نريد أن يستخدم كل نص عن قصد النمط المحدد ونمط الخط واللون المحدد من مواصفات التصميم.

  • هذه هي قاعدة Lint التي نستخدمها.

  • وأخيرًا، على غرار ScaffoldPaddingDetector، لدينا قاعدة Lint مخصّصة تفرض استخدام معدِّل الإدخال في كل دالة مركّبة لدينا.

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

الخاتمة

  • هذه هي النقاط الثلاث الرئيسية التي نودّ أن تستخلصها من هذا العرض التقديمي.

  • أولاً، في نهاية عام 2026، نرى أنّ Compose هي مجموعة أدوات واجهة مستخدم ناضجة ومثبتة على نطاق واسع.

  • ويعتمد نظام Android نفسه على Compose في المقام الأول.

  • في وقت سابق من هذا العام في مؤتمر Google I/O، أعلنّا أنّ جميع مكتبات واجهة المستخدم وجميع مسارات الوكلاء ستكون متوافقة مع Compose أولاً.

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

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

  • وأشكرك مرة أخرى على وقتك.

الرمز

مقتطفات الرمز البرمجي

مقتطف Kotlin في الدقيقة 16:09 في فيديو "تحسين الموثوقية والسرعة"
@Composable
fun PurchaseRow(onClick: () -> Unit, modifier: Modifier) {
  Row(modifier) {
    Text("20% off sale")
    if (LocalExpts.current.useButtonV2) {
      ButtonV2("Buy", onClick = onClick)
    } else {
      ButtonV1("Buy", onClick = onClick)
    }
  }
}