الغوص في Jetpack يؤلف

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



تجربة إطار واجهة مستخدم جديد لتطبيقات Android


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

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


الروبوت يكشف Jetpack يؤلف. التوضيح: إيمانويل باجيلا

Jetpack يؤلف إلى الإنقاذ


لذلك ، بعد مشاهدة ما الجديد في Android من مؤتمر Google I / O 2019 ، بدأت على الفور التعامل مع Compose وحاولت معرفة المزيد عنه. إن Compose عبارة عن مجموعة أدوات لواجهة المستخدم التفاعلية تم تطويرها بالكامل بواسطة Kotlin. يبدو "إنشاء" مشابهًا جدًا لأطر واجهة المستخدم الحالية مثل React أو Litho أو Flutter.

يوجد الهيكل الحالي لإطار عمل نظام أندرويد UI منذ عام 2008 ، ومع مرور الوقت أصبح أكثر تعقيدًا ، من الصعب الحفاظ عليه. يهدف Jetpack Compose إلى البدء من البداية ، مع مراعاة فلسفة المكونات الحديثة. تتم كتابة الإطار مع مراعاة الأهداف الرئيسية التالية:

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

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

تطبيق بسيط مع تأليف: مرحبا العالم


دعونا نلقي نظرة على الكود لتطبيق Hello World البسيط مع Jetpack Compose.

class ComposeActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MyApp() } } } @Composable fun MyApp() { MaterialTheme { Text(text = "Hello world!", style = +themeTextStyle { h3 }) } } } 

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

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

مقدمة الدولة


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

 @Composable fun MyApp() { MaterialTheme { Counter() } } @Composable fun Counter() { val amount = +state { 0 } Column { Text(text = "Counter demo") Button(text = "Add", onClick = { amount.value++ }) Button(text = "Subtract", onClick = { amount.value-- }) Text(text = "Clicks: ${amount.value}") } } 


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


إطلاق تطبيق تجريبي

تتم تهيئة حالة amount مع +state { 0 } . في محاولة لمعرفة نوع السحر ، قمت بالزحف إلى شفرة المصدر. هذا هو رأيي ، على الرغم من أنني ما زلت غير متأكد من أنني أفهم تمامًا كل شيء.

state {...} تنشئ Effect< State < T < code>> . فئة Effect هي فئة غامضة تحتوي على مجموعة من التعليمات البرمجية القابلة للتنفيذ التي يتم تشغيلها بشكل موضعي في سياق التكوين. تحتوي فئة الحالة على قيمة واحدة بنوع Model ، مما يجعل هذه القيمة قابلة للملاحظة بشكل أساسي. عامل التشغيل + هو مشغل مؤقت يحل State من Effect .

نماذج الحالة المخصصة


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

 @Model class CounterModel { var counter: Int = 0 var header = "Counter demo" fun add() { counter++ } fun subtract() { counter-- } } 


باستخدام التعليق التوضيحي @Model ، يجعل المكون الإضافي لـ @Model Compiler جميع المتغيرات في النموذج الخاص بك قابلاً للملاحظة بحيث يمكن استخدامها لإعادة ترتيب الأدوات. لنقم بتحديث تطبيقنا المصغر لاستخدام CounterModel :

 @Composable fun Counter(counterModel: CounterModel) { Column { CounterHeader(counterModel) AddSubtractButtons(counterModel) CounterLabel(counterModel) } } @Composable fun CounterHeader(counterModel: CounterModel) { Text(text = counterModel.header) } @Composable fun AddSubtractButtons(counterModel: CounterModel) { Button( text = "Add", onClick = { counterModel.add() }) Button( text = "Subtract", onClick = { counterModel.subtract() }) } @Composable fun CounterLabel(counterModel: CounterModel) { Text(text = "Clicks: ${counterModel.counter}") } 


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

لا مزيد من الرأي


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

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

 @Composable private fun DrawFillRect(brush: Brush) { Draw { canvas, parentSize -> val paint = Paint() brush.applyBrush(paint) canvas.drawRect(parentSize.toRect(), paint) } } 


التعليمات البرمجية المصدر لـ DrawFillRect المستخدمة داخل عنصر واجهة المستخدم Divider.
إذا نظرنا إلى Layout Inspector من خلال تشغيل أحد التطبيقات ViewGroups من Google ، فسوف نرى بوضوح أنه عند بدء تشغيل تطبيق Android باستخدام ViewGroups لا توجد View أو ViewGroups . نرى FrameLayout يحتوي على CraneWrapper التي أنشأناها في الكود ، ومن هناك يتم عرض التسلسل الهرمي لـ "إنشاء واجهة المستخدم" على الشاشة.


تخطيط المفتش يتفقد Jetpack يؤلف.

يعني عدم وجود طرق عرض أيضًا أن Jetpack Compose لا يمكنه استخدام طرق العرض المتوفرة حاليًا ، مثل android.widget.Button ، ويجب أن ينشئ جميع عناصر واجهة المستخدم من البداية. إذا نظرت ، على سبيل المثال ، إلى Flutter ، التي تستخدم نفس الطريقة ، يمكنك أن ترى أن هذا عمل شاق. هذا هو أحد أسباب احتياج Jetpack Compose إلى وقت قبل أن يصبح جاهزًا للاستخدام في الإنتاج.

جميع العناصر هي الحاجيات.


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

 Padding(padding = 16.dp) { Button(text = "Say hello", onClick = { ... }) } 


ربط الكود بواجهة المستخدم


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

 Column { listOf("John", "Julia", "Alice", "Mark").forEach { Text(text = it) } } 


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

متوافق مع تطبيقات Android الخاصة بك


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

 @Composable @GenerateView fun Greeting(name: String) { /* … */ } //  -  layout.xml <GreetingView app:name=”John” /> 

استنتاج


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

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

اقرأ مقالتي Try Jetpack Compose اليوم لمعرفة كيفية ربط ما قبل alpha. أيضًا ، أعتقد أنه سيكون من الممتع جدًا أن تشاهد مقطع فيديو على قوالب واجهة تعريفية باستخدام Google I / O.
إنني أتطلع إلى متى يمكنني استخدام Compose في تطبيقات Android الحقيقية!

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

Source: https://habr.com/ru/post/ar458106/


All Articles