في الآونة الأخيرة ، لفتت الأنباء انتباهي إلى أن
الإصدار التالي
من Flutter (1.9) تم إصداره ، والذي يعد بمختلف الأشياء الجيدة ، بما في ذلك الدعم المبكر لتطبيقات الويب.
في العمل ، أقوم بتطوير تطبيقات الهاتف المحمول على React Native ، لكنني أنظر إلى Flutter بفضول. بالنسبة لأولئك الذين ليسوا على دراية: في Flutter ، يمكنك الآن إنشاء تطبيقات لنظامي Android و iOS ، يتم إعداد دعم تطبيقات الويب للإصدار ، وهناك أيضًا خطط لدعم سطح المكتب.
هذا هو "حلقة واحدة لحكم كل شيء."
بعد أن أدارت رأيي على مدى يومين حول نوع التطبيق الذي يمكنك محاولة تقديمه ، قررت اختيار مهمة باستخدام علامة النجمة - ما الذي نحتاجه في هذه المسارات البالية؟ تأرجح على سطح المكتب وتغلب على الصعوبات البطولية! واستشرافا للمستقبل ، سأقول أنه لا توجد صعوبات تقريبا.
تحت القص - قصة حول كيفية حل مهام برنامج React Native المعتاد باستخدام أدوات Flutter ، بالإضافة إلى الانطباع العام للتكنولوجيا.

بالتفكير في ميزات Flutter التي أود "لمسها" ، قررت أنه في طلبي يجب أن يكون:
- طلبات إلى API البعيد ؛
- التحولات بين الشاشات.
- الرسوم المتحركة الانتقالية
- مدير الدولة - استرجاع أو شيء مماثل.
لا أعرف كيفية النسخ الخلفي ، لذلك قررت البحث عن واجهة برمجة تطبيقات مفتوحة تابعة لجهة خارجية. نتيجة لذلك ، استقرت على هذا المورد -
دورات CBR في XML و JSON ، API . حسنًا ، لقد قررت هنا أخيرًا وظيفة التطبيق: ستكون هناك شاشتان ، على الشاشة الرئيسية قائمة بالعملات بسعر CBR ، عندما تنقر فوق عنصر قائمة ، نفتح شاشة تحتوي على معلومات مفصلة.
تدريب
نظرًا لأن أمر
flutter create
لا يعرف بعد كيفية إنشاء مشروع لنظام التشغيل Windows / Linux (فقط نظام Mac معتمد حاليًا ، استخدم علامة -
--macos
لهذا) ، يجب عليك استخدام
هذا المستودع ، حيث يوجد مثال مُعد. نقوم باستنساخ المستودع ، ونأخذ
example
المجلد من هناك ، إذا لزم الأمر ، نعيد تسميته ونواصل العمل فيه.
نظرًا لأن دعم الأنظمة الأساسية لسطح المكتب لا يزال قيد التطوير ، فلا تزال بحاجة إلى القيام بعدد من المعالجات. للوصول إلى الميزات قيد التطوير ، قم بتشغيلها في الجهاز:
flutter channel master flutter upgrade
بالإضافة إلى ذلك ، يجب أن تخبر Flutter أنه يمكنه استخدام النظام الأساسي الخاص بك:
flutter config --enable-linux-desktop
أو
flutter config --enable-macos-desktop
أو
flutter config --enable-windows-desktop
إذا سارت الأمور على ما يرام ، فمن خلال تشغيل أمر
flutter doctor
يجب أن تشاهد ناتجًا مشابهًا:

لذا ، المشهد جاهز ، الجمهور في القاعة - يمكننا أن نبدأ.
تصميم
أول ما يلفت انتباهك بعد React Native هو عدم وجود لغة ترميز خاصة لا JSX. يفرض عليك الرفرفة أن تكتب منطق الترميز والمنطق في
دارت . في البداية ، هذا أمر مزعج: المظهر ليس لديه ما يلفت الانتباه ، الكود يبدو مرهقًا ، وحتى هذه الأقواس موجودة في نهاية المكون!
على سبيل المثال ، مثل:

وهذا ليس الحد! يجدر إزالة واحدة في المكان الخطأ ويضمن لك قضاء وقت ممتع (لا).
بالإضافة إلى ذلك ، نظرًا لخصائص مكونات التصميم في Flutter ، بالنسبة للمكونات الكبيرة ، فإن المسافة البادئة من الحافة اليسرى من المحرر تزداد بسرعة كبيرة ، ومعها يتم إغلاق عدد الأقواس.
هذه الميزة هي أن في أنماط Flutter هي نفس المكونات (لتكون أكثر دقة - الحاجيات).
إذا كان في React Native لترتيب ثلاثة أزرار في صف واحد داخل
View
بحيث تقوم بتوزيع مساحة الحاوية بالتساوي ، يكفي أن
flexDirection: 'row'
بتعيين
flexDirection: 'row'
للعرض في الأنماط وإضافة
flex: 1
للأزرار في الأنماط ، ثم يحتوي Flutter على مكون منفصل
Row
لترتيب العناصر في صف واحد منفصل عن "قابلية التوسع" لعنصر على كامل المساحة المتاحة:
Expanded
.
نتيجة لذلك ، بدلا من
<View style={{height: 100, width:300, flexDirection: 'row'}}> <Button title='A' style={{flex:1}}> <Button title='B' style={{flex:1}}> <Button title='C' style={{flex:1}}> </View>
علينا أن نكتب مثل هذا:
Container( height: 100, width: 300, child: Row( children: <Widget>[ Expanded( child: RaisedButton( onPressed: () {}, child: Text('A'), ), ), Expanded( child: RaisedButton( onPressed: () {}, child: Text('B'), ), ), Expanded( child: RaisedButton( onPressed: () {}, child: Text('C'), ), ), ], ), )
أكثر مطول ، أليس كذلك؟
أو ، على سبيل المثال ، تريد إضافة إطار بحواف مستديرة إلى هذه الحاوية. في React Native ، نضيف ببساطة إلى الأنماط:
borderRadius: 5, borderWidth: 1, borderColor: '#ccc'
في Flutter ، يتعين علينا إضافة شيء مثل هذا إلى وسيطات الحاوية:
decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(5)), border: Border.all(width: 1, color: Color(0xffcccccc)) ),
بشكل عام ، في البداية ، تحولت ترميمي إلى أوراق ضخمة من الشفرة ، حيث كسر الشيطان ساقه. ومع ذلك ، ليس كل شيء سيء للغاية.
أولاً ، يجب تقسيم المكونات الكبيرة بالطبع - في عناصر واجهة مستخدم منفصلة أو على الأقل في أساليب فئة عنصر واجهة المستخدم.
ثانياً ، يساعد البرنامج المساعد Flutter في VS Code كثيرًا - في الصورة أعلاه ، يتم توقيع التعليقات على الأقواس بواسطة البرنامج المساعد نفسه (وهي غير قابلة للتشكيل) ، مما يساعد على عدم الخلط بين قوسين. بالإضافة إلى أدوات التنسيق التلقائي - بعد نصف ساعة ، تعتاد على الضغط بشكل دوري على
Ctrl+Shift+I
لتنسيق الرمز.
بالإضافة إلى ذلك ، أصبح بناء جملة لغة Dart في الإصدار الثاني أكثر متعة ، لذلك بنهاية اليوم استمتعت بالفعل باستخدامه. غير عادية؟ نعم. ولكن ليس غير سارة.
طلبات API
في React Native ، للحصول على البيانات من بعض واجهة برمجة التطبيقات ، نستخدم عادةً طريقة
fetch
، والتي تُرجع
Promise
لنا.
في الرفرفة ، الوضع مشابه. بعد النظر في الأمثلة الموجودة في الوثائق ، أضفت حزمة http إلى
pubspec.yaml
(
pubspec.yaml
لـ
package.json
من عالم JS) وكتبت شيئًا مثل هذا:
Future<http.Response> getAnything() { return http.get(URL); }
كائن
Future
مشابه جدًا لمعنى "الوعد" ، لذلك كل شيء شفاف هنا. حسنًا ، لتسلسل / إلغاء تسلسل كائنات json ، يمكنك استخدام مفهوم فئات النماذج باستخدام طرق خاصة من
fromJSON
/
toJSON
. يمكنك قراءة المزيد حول هذا في
الوثائق .
الانتقال بين الشاشات
على الرغم من أنني كنت أصنع تطبيقًا لسطح المكتب ، فمن وجهة نظر Flutter ، لا يوجد فرق في النظام الأساسي الذي يدور حوله. حسنًا ، هذا هو الحال بالنسبة لي ، بشكل عام - لا أعرف. في الواقع ، فإن نافذة النظام التي يتم فيها تشغيل تطبيق الرفرفة هي نفس شاشة الهاتف الذكي.
يعد الانتقال بين الشاشات بسيطًا للغاية: فنحن ننشئ فئة لعنصر واجهة مستخدم الشاشة ، ثم نستخدم فئة
Navigator
القياسية.
في أبسط الحالات ، قد يبدو مثل هذا:
RaisedButton( child: Text('Go to Detail'), onPressed: () { Navigator.of(context).push<void>(MaterialPageRoute(builder: (context) => DetailScreen())); }, )
إذا كان التطبيق الخاص بك يحتوي على العديد من الشاشات ، فمن المعقول أولاً إعداد قاموس للطرق ، ثم استخدام طريقة
pushNamed
. مثال صغير من الوثائق:
class NavigationApp extends StatelessWidget {
بالإضافة إلى ذلك ، يمكنك إعداد رسم متحرك خاص للتبديل بين الشاشات وكتابة شيء مثل هذا:
Navigator.of(context).push<void>(ScaleRoute(page: DetailScreen()));
هنا
ScaleRoute
هي فئة خاصة لإنشاء الرسوم المتحركة الانتقالية. يمكن العثور على أمثلة جيدة لهذه الرسوم المتحركة
هنا .
إدارة الدولة
يحدث أننا بحاجة إلى الوصول إلى بعض البيانات من أي جزء من طلبنا. في React Native ، غالبًا ما
redux
استخدام
redux
(إن لم يكن في معظم الأحيان) لهذه الأغراض.
بالنسبة إلى Flutter ، يوجد
مستودع يوضح أمثلة على استخدام أبنية التطبيقات المختلفة - هناك Redux و MVC و MVU ، وحتى تلك التي لم أسمع عنها من قبل.
بعد أن نفشت قليلا في هذه الأمثلة ، قررت التوقف عن
Provider
.
بشكل عام ، الفكرة بسيطة للغاية: نقوم بإنشاء فصل خاص
ChangeNotifier
فئة
ChangeNotifier
، حيث سنقوم بتخزين بياناتنا ، وتحديثها باستخدام أساليب هذه الفئة ، والتقاطها من هناك إذا لزم الأمر. راجع
وثائق الحزمة لمزيد من التفاصيل.
للقيام بذلك ، قم بإضافة حزمة
provider
إلى
pubspec.yaml
وإعداد فئة موفر. في حالتي ، يبدو الأمر كما يلي:
import 'package:flutter/material.dart'; import 'package:rates_app/models/rate.dart'; class RateProvider extends ChangeNotifier { Rate currentrate; void setCurrentRate(Rate rate) { this.currentrate = rate; notifyListeners(); } }
Rate
هنا هو فئة نموذج العملة الخاصة بي (مع
name
الحقول ،
code
،
value
، إلخ) ، التيار هو الحقل الذي سيتم تخزين العملة المحددة فيه ، و
setCurrentRate
هو الطريقة التي يتم من خلالها
currentrate
القيمة الحالية.
لإرفاق مزودنا بالتطبيق ، نقوم بتغيير رمز فئة التطبيق:
@override Widget build(BuildContext context) { return ChangeNotifierProvider( builder: (context) => RateProvider(),
هذا كل شيء الآن ، إذا أردنا حفظ العملة المحددة ، فسنكتب شيئًا من هذا القبيل:
Provider.of<RateProvider>(context).setCurrentRate(rate);
وإذا كنا نرغب في الحصول على القيمة المخزنة ، فإن هذا:
var rate = Provider.of<RateProvider>(context).currentrate;
كل شيء شفاف تمامًا ولا يوجد صفيحة (على عكس Redux). بالطبع ، ربما بالنسبة للتطبيقات الأكثر تعقيدًا ، فإن كل شيء سينتهي ليس بسلاسة ، ولكن بالنسبة لأولئك الذين على سبيل المثال ، النبيذ النقي.
بناء التطبيق
من الناحية النظرية ، يتم استخدام الأمر
flutter build <platform>
لإنشاء التطبيق. في الممارسة العملية ، عندما قمت بتنفيذ الأمر
flutter build linux
، تلقيت هذه الرسالة:

"لم تؤلم" ، حسب اعتقادي ، شعرت بالرعب من وزن مجلد الإنشاء - 287.5 ميجابايت - وبسبب بساطة روحي ، قمت بحذف هذا المجلد إلى الأبد. كما اتضح - عبثا.
بعد حذف دليل
build
، توقف المشروع عن البدء. لم أستطع استعادته ، لذلك قمت بنسخه من المثال الأصلي. لم يساعد - أقسم جامع في الملفات المفقودة.
بعد إجراء القليل من البحث ، اتضح أنه يوجد في هذا المجلد ملف
snapshot_blob.bin.d
، والذي يبدو أنه يحتوي على مسارات لجميع الملفات المستخدمة في المشروع. أضفت المسارات المفقودة وعملت.
وبالتالي ، في هذه اللحظة لا يعرف Flutter كيفية تحضير تصميمات الإصدار لسطح المكتب. على أي حال ، لينكس.
بشكل عام ، إذا أغمضت عينيك على هذا الطرح ، فقد تحول التطبيق بالطريقة التي أردتها وأبدو
علاوة
نمر إلى المكافأة الموعودة.
حتى في مرحلة كتابة التطبيق ، كنت أرغب في التحقق من صعوبة تحويله إلى منصات أخرى. لنبدأ مع الهاتف الخليوي.
بالتأكيد هناك طريقة أقل وحشية ، لكنني قررت أن أقصر الطرق مباشر. لذلك ، قمت ببساطة بإنشاء مشروع
pubspec.yaml
جديد ، ونقل ملف
pubspec.yaml
assets
fonts
وأدلة
lib
إليه وأضفت السطر إلى
AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
بدأ التطبيق بضربة جزاء وحصلت على هذا
في البداية ، كان علي أن العبث بالويب. لم أكن أعرف كيفية إنشاء مشروع ويب ، لذلك استخدمت الإرشادات من الإنترنت ، والتي لم تنجح لسبب ما. كنت أرغب في البصق بالفعل ، ولكن صادفت
هذا الدليل.
ونتيجة لذلك ، أصبح كل شيء بسيطًا بقدر الإمكان - كان من الضروري فقط تضمين دعم لتطبيقات الويب. الضغط من الدليل:
flutter channel master flutter upgrade flutter config --enable-web cd <into project directory> flutter create . flutter run -d chrome
ثم قمت بنقل الملفات اللازمة لهذا المشروع بنفس الطريقة الهمجية وتلقيت مثل هذا
الانطباعات العامة
في البداية ، كان العمل مع Flutter أمرًا غير اعتيادي ، وحاولت دائمًا استخدام الأساليب المعتادة من React Native ، وهذا يتدخل. أيضا ، كان بعض التكرار من رمز السهام مزعج بعض الشيء.
بعد أن حصلت على يدي (والأقماع) قليلاً ، بدأت أرى مزايا Flutter على React Native. سأذكر بعض.
اللغة دارت هي لغة مفهومة تماما ولطيفة مع كتابة ثابتة قوية. بعد جافا سكريبت ، كان مثل التنفس من الهواء النقي. توقفت عن الخوف من كسر الشفرة في وقت التشغيل وكان شعورًا ممتعًا. قد يقول شخص ما أن هناك Flow و TypeScript ، لكن الأمر ليس كذلك - في مشاريعنا استخدمنا كلاهما ، وشيء آخر دائماً ما كسر في مكان ما. عندما أكتب في React Native ، لا يسعني إلا أن أشعر أن الكود الخاص بي موجود في الدعائم القابلة للتعديل والتي يمكن أن تنكسر في أي وقت. مع Flutter ، لقد نسيت هذا الشعور ، وإذا كان السعر هو تكرار الكود ، فأنا مستعد لدفعه.
منصة . في React Native ، تستخدم مكونات أصلية وهذا جيد عمومًا. ولكن لهذا السبب ، يجب عليك في بعض الأحيان كتابة تعليمات برمجية خاصة بالنظام الأساسي ، وكذلك التقاط الأخطاء الخاصة بكل منصة. يمكن أن يكون متعب بشكل لا يصدق. مع Flutter ، يمكنك نسيان هذه المشاكل مثل كابوس (على الرغم من أنه قد لا يكون الأمر سلسًا في التطبيقات الكبيرة).
البيئة . مع البيئة في React Native ، كل شيء محزن. تتساقط المكونات الإضافية لـ vscode باستمرار ، ويمكن لمصحح الأخطاء أن يلتهم 16 gig من المنطوق و 70 gig من المبادلة ، ويعلق النظام بإحكام (من التجربة الشخصية) ، وسيناريو تصحيح الخطأ الأكثر شيوعًا: "إزالة node_modules ، وتثبيت الحزم مرة أخرى ومحاولة إعادة التشغيل عدة مرات." هذا يساعد عادة ، ولكن bljad! ليس كذلك يجب أن يكون ، ليس كذلك.
بالإضافة إلى ذلك ، سيتعين عليك تشغيل AndroidStudio و Xcode بشكل دوري ، لأن البعض يوضع بهذه الطريقة فقط (في الإنصاف ، مع إصدار RN 0.60 أصبح هذا أفضل).
على هذه الخلفية ، فإن البرنامج المساعد الرسمي Flutter لـ vscode يبدو جيدًا للغاية. تتيح لك تلميحات التعليمات البرمجية التعرف على النظام الأساسي دون النظر إلى الوثائق ، والتنسيق التلقائي يحل المشكلة مع نمط الترميز ، المصحح العادي ، إلخ.
بشكل عام ، يبدو وكأنه أداة أكثر نضجا.
عبر منصة . تعلن React Native مبدأ "تعلم مرة واحدة ، والكتابة في كل مكان" - بمجرد أن تتعلم ، يمكنك الكتابة لمنصات مختلفة. صحيح ، تحت كل منصة سوف تواجه مشاكل خاصة به. ولكن ربما يكون هذا نتيجة عدم نضج React Native - في الوقت الحالي ، أحدث إصدار ثابت هو 0.61. ربما مع إصدار الإصدار 1.0 ، فإن معظم هذه المشاكل سوف تختفي.
يشبه نهج رفرفة الكتابة مرة واحدة ، وتجميعها في كل مكان. وحتى إذا لم يكن سطح المكتب جاهزًا للإنتاج في الوقت الحالي ، فإن الويب أيضًا في وضع alpha ، لكن كل شيء يذهب إلى ذلك. والقدرة على الحصول على قاعدة رمز واحد لجميع المنصات هي حجة قوية.
بطبيعة الحال ، لا يخلو Flutter أيضًا من العيوب ، لكن تجربة بسيطة في استخدامه لا تسمح لي بالتعرف عليها. لذلك إذا كنت ترغب في تقييم أكثر موضوعية - لا تتردد في خصم تأثير الجدة.
بشكل عام ، تجدر الإشارة إلى أن رفرفة تركت معظمها مشاعر إيجابية ، على الرغم من أن لديه مساحة للنمو. والمشروع التالي سأكون أكثر استعدادًا للبدء فيه ، وليس على React Native.
يمكن العثور على الكود المصدري للمشروع على
جيثب .
ملاحظة: أغتنم هذه الفرصة لأهنئ جميع المشاركين في يوم المعلم السابق.