يتم استخدام المشغلين لحل مشكلة تحويل الكائنات التي يمكن ملاحظتها. يتم استخدام المشغلين لتعديل الأحداث المنبعثة من خلال الملاحظة بين المشترك والمراقبة النهائية. يوفر Rxjava العديد من المشغلين المفيدين.
على سبيل المثال ، يتم استخدام مشغل الخريطة لتحويل حدث إلى آخر.
rocartable.just ("Hello ، World!") .MAP (Func1 <string ، string> () {Override Public String Call (سلسلة S) {return S + "-dan" ؛}}) .Subscribe (s -> system.out.println (s)) ؛ يمكن تبسيط استخدام Lambda إلى
يمكن ملاحظته.
أليس هذا رائع؟ يتم استخدام مشغل MAP () لتحويل الكائن الملحوظ. يقوم مشغل الخريطة بإرجاع كائن يمكن ملاحظته ، بحيث يمكن تنفيذ استدعاء السلسلة ، ويتم استخدام مشغل الخريطة عدة مرات على كائن يمكن ملاحظته ، وأخيراً يتم تمرير أبسط البيانات إلى كائن المشترك.
مشغل الخريطة المتقدمة
ما هو أكثر إثارة للاهتمام حول مشغل الخريطة هو أنه لا يجب إرجاع النوع الذي تم إرجاعه بواسطة الكائن الذي يمكن ملاحظته. يمكنك استخدام مشغل الخريطة لإرجاع كائن يمكن ملاحظته ينبعث من نوع البيانات الجديد.
على سبيل المثال ، في المثال أعلاه ، لا يهتم المشترك بالسلسلة التي تم إرجاعها ، ولكنها تريد قيمة التجزئة للسلسلة.
يمكن ملاحظته.
مثيرة جدا للاهتمام ، أليس كذلك؟ إرجاعنا الأولي الذي يمكن ملاحظته إلى سلسلة ، بينما يتلقى المشترك النهائي عددًا صحيحًا. بالطبع ، يمكن أن يؤدي استخدام Lambda إلى تبسيط الكود:
يمكن ملاحظته.
كما ذكرنا سابقًا ، كلما قل الاشتراك ، كان ذلك أفضل. دعنا نضيف مشغل خريطة آخر.
opplication.just ("Hello ، World!") .map (s -> S.HashCode ()) .map (i -> integer.toString (i)) .Subscribe (s -> system.out.println (s)) ؛ غير مقتنع؟
هل تعتقد أن مثالنا بسيط للغاية لإقناعك؟ تحتاج إلى فهم النقطتين التاليتين:
1. يمكن ملاحظته والمشترك في فعل أي شيء
يمكن ملاحظته أن يكون استعلام قاعدة البيانات ، ويتم استخدام المشترك لعرض نتائج الاستعلام ؛ يمكن أن يكون الملاحظة حدثًا نقرة على الشاشة ، ويتم استخدام المشترك للرد على أحداث النقر ؛ يمكن أن يكون الملاحظة طلب شبكة ، ويتم استخدام المشترك لعرض نتائج الطلب.
2. يمكن ملاحظتها والمشترك مستقلة عن عملية التحول الوسيطة.
يمكن إضافة أو انخفاض أي عدد من الخرائط بين الملاحظة والمشترك. النظام بأكمله يمكن دمجه بشكل كبير ، وبيانات التشغيل هي عملية بسيطة للغاية.
مثال
1. التحضير
افترض أن لدي طريقة مثل هذه:
تقوم هذه الطريقة بإرجاع قائمة عنوان URL لموقع الويب بناءً على سلسلة الإدخال (Ahha ، محرك البحث)
يمكن ملاحظته <list <string> Query (نص سلسلة) ؛
الآن أريد إنشاء نظام قوي يمكنه الاستعلام عن الأوتار وعرض النتائج. بناءً على محتوى المدونة السابقة ، قد نكتب الرمز التالي:
Query ("Hello ، World!") .Subscribe (urls -> {for (url url: urls) {system.out.println (url) ؛}}) ؛بالطبع ، لا يمكن التسامح مع هذا النوع من التعليمات البرمجية ، لأن الكود أعلاه تسبب لنا في فقدان القدرة على تغيير تدفق البيانات. بمجرد أن نريد تغيير كل عنوان URL ، يمكننا فقط القيام بذلك في المشترك. لم نستخدم مثل هذا المشغل الخريطة الرائعة! ! !
بالطبع ، يمكنني استخدام مشغل الخريطة. إدخال الخريطة هي قائمة URLS. عند المعالجة ، لا يزال يحتاج إلى اجتياز كل منهما ، وهو أيضًا مؤلم للغاية.
لحسن الحظ ، هناك أيضًا طريقة الملاحظة. من () ، والتي تتلقى مجموعة كمدخل ثم يقوم بإخراج عنصر للمشترك في وقت واحد:
يمكن ملاحظته. من ("url1" ، "url2" ، "url3") .Subscribe (url -> system.out.println (url)) ؛ دعونا نستخدم هذه الطريقة للمشهد الآن فقط:
Query ("Hello ، World!") .SubScribe (urls -> {orbordable.from (urls) .Subscribe (url -> system.out.println (url)) ؛}) ؛
على الرغم من إزالة كل حلقة ، إلا أن الكود لا يزال فوضويًا. لا تبدو الاشتراكات المتداخلة المتعددة قبيحة وصعبة التعديل فحسب ، بل بشكل جدي ، ستدمر بعض ميزات Rxjava التي لم نذكرها بعد.
2. التحسين
المنقذ هنا ، هو flatmap ().
يمكن ملاحظته. انظر مباشرة إلى الكود:
Query ("Hello ، World!") .flatmap (func1 جديد <string> ، يمكن ملاحظته <string >> () {Override public callable <string> call (list <string> urls) {return rocartable.from (urls) ؛}}) .subscrib لقد نشرت هنا رمز الوظيفة بأكمله لتسهيلك لفهم ما يجري. يمكن أن يؤدي استخدام Lambda إلى تبسيط طول الرمز بشكل كبير:
الاستعلام ("Hello ، World!") .flatmap (urls -> rocartable.from (urls)) .Subscribe (url -> system.out.println (url)) ؛هل تبدو Flatmap () غريبة؟ لماذا يعود آخر يمكن ملاحظته؟ النقطة الرئيسية في فهم FlatMap هي أن الإخراج الجديد القابل للملاحظة من FlatMap هو بالضبط ما نريد تلقيه في المشترك. لم يعد المشترك الآن يتلقى قائمة <string> ، ولكن بدلاً من ذلك يتلقى بعض السلاسل المفردة من الأعمدة ، تمامًا مثل إخراج الملاحظة. من ().
هذا الجزء هو أيضًا الجزء الأكثر صعوبة عندما تعلمت لأول مرة rxjava. بمجرد أن أدركت ذلك فجأة ، تم حل العديد من الأسئلة في Rxjava.
3. يمكن أن يكون أفضل
FlatMap () ليست فكرة أفضل ، يمكنها إرجاع أي كائن يمكن ملاحظته الذي يريد إرجاعه.
على سبيل المثال ، الطريقة التالية:
// إرجاع عنوان الموقع الإلكتروني ، وإذا كان 404 ، فالرئة Null يمكن ملاحظتها <string> getTitle (url url string) ؛
بعد المثال السابق ، الآن لا أريد طباعة عنوان URL بعد الآن ، ولكن بدلاً من ذلك ، قم بطباعة عنوان كل موقع ويب أتلقاه. المشكلة هي أن طريقتي يمكن أن تمر فقط في عنوان URL واحد في وقت واحد ، وقيمة الإرجاع ليست سلسلة ، ولكن كائن الملاحظة الذي يخرج سلسلة. يمكن باستخدام FlatMap () ببساطة حل هذه المشكلة.
Query ("Hello ، World!") .flatmap (urls -> rocartable.from (urls)) .flatmap (func1 <string ، strookable <string> () { @Override publicable <string> call (string url) {return getTitle (url) ؛}}}). 4. استخدم Lambda:
Query ("Hello ، World!") .flatmap (urls -> rocartable.from (urls)) .flatmap (url -> getTitle (url)) .Subscribe (title -> system.out.println (title)) ؛ ألا تشعر بأنها لا تصدق؟ يمكنني في الواقع الجمع بين طرق متعددة مستقلة لإرجاع كائنات يمكن ملاحظتها معًا! وسيم جدا!
أكثر من ذلك ، قمت أيضًا بدمج مكالمات واجهات برمجة التطبيقات في مكالمة بالسلاسل. يمكننا ربط أكبر عدد ممكن من مكالمات API قدر الإمكان. يجب على الجميع أن يعرفوا مدى مؤلمه في مزامنة جميع مكالمات API ثم الجمع بين نتائج رد الاتصال لجميع مكالمات API في البيانات المراد عرضها. هنا نجحنا في تجنب Callback Hell (متعدد الطبقات متداخلة متداخلة ، مما يجعل القراءة والصيانة المدونة). الآن يتم لف كل المنطق في هذه المكالمة البسيطة المستجيبة.
5. المشغلون الأثرياء <br /> حتى الآن ، تواصلنا مع اثنين من المشغلين ، وهناك المزيد من المشغلين في Rxjava ، فكيف نستخدم المشغلين الآخرين لتحسين التعليمات البرمجية لدينا؟
GetTitle () يعيد فارغ إذا لم يكن عنوان URL موجودًا. لا نريد إخراج "NULL" ، ثم يمكننا تصفية القيمة الفارغة من قائمة العنوان التي تم إرجاعها!
Query ("Hello ، World!") .flatmap (urls -> rocartable.from (urls)) .flatmap (url -> getTitle (url)) .filter (title -> title! = null) .subscribe (title -> system.Ut.println (title)) ؛يقوم Filter () بإخراج نفس العناصر مثل الإدخال وترشيح تلك التي لا تفي بمعايير الشيكات.
إذا كنا نريد فقط ما يصل إلى 5 نتائج:
الاستعلام ("Hello ، World!") .flatmap (urls -> rocartable.from (urls)) .flatmap (url -> getTitle (url)) .filter (title -> title! = null) .take (5) .Subscribe (title -> system.Out.println (title)) ؛خذ () يخرج الحد الأقصى لعدد النتائج.
إذا أردنا حفظ كل عنوان على القرص قبل الطباعة:
الاستعلام ("Hello ، World!") .flatmap (urls -> rocartable.from (urls)) .flatmap (url -> getTitle (url)) .filter (title -> title! = null) .take (5) .doonnext (title -QueTitle (title)يتيح لنا Doonext () القيام ببعض الأشياء الإضافية قبل إخراج عنصر في وقت واحد ، مثل حفظ العنوان هنا.
هل من السهل معرفة مدى سهولة تشغيل تدفق البيانات هنا؟ يمكنك إضافة العديد من العمليات كما تريد ولا تعبث رمزك.
يحتوي Rxjava على عدد كبير من المشغلين. عدد المشغلين مخيف بعض الشيء ، لكن الأمر يستحق التحقق من واحد تلو الآخر حتى تتمكن من معرفة المشغلين التي يمكن استخدامها. قد يستغرق الأمر بعض الوقت لفهم هؤلاء المشغلين ، ولكن بمجرد أن تفهم ، ستحصل على قوة Rxjava تمامًا.
يمكنك حتى كتابة مشغلي مخصص! لا تنوي هذه المدونة تخصيص المشغل. إذا كنت تريد ، يرجى Google بنفسك.
ما هو شعورك؟
حسنًا ، أنت متشكك ومن الصعب إقناعه ، فلماذا تهتم بهؤلاء المشغلين؟
لأن المشغلين يسمحون لك بفعل أي شيء لتيار البيانات.
يمكن لربط سلسلة من المشغلين إنجاز المنطق المعقد. يتم تقسيم الكود إلى سلسلة من القصاصات التي يمكن دمجها. هذا هو سحر برمجة الوظائف التفاعلية. كلما استخدمته أكثر ، كلما تغيرت تفكيرك في البرمجة.
بالإضافة إلى ذلك ، يسهل Rxjava أيضًا بالنسبة لنا معالجة البيانات. في المثال الأخير ، نسمي اثنين من واجهات برمجة التطبيقات ، معالجة البيانات التي يتم إرجاعها بواسطة واجهة برمجة التطبيقات ، وحفظها على القرص. لكن مشتركنا لا يعرف هذا ، فهو يعتقد فقط أنه يتلقى كائن <string> يمكن ملاحظته. عبوة جيدة أيضا تجلب الراحة الترميز!
في الجزء الثالث ، سأقدم بعض الميزات الرائعة الأخرى لـ Rxjava ، مثل معالجة الأخطاء والتزامن ، والتي لا تستخدم مباشرة لمعالجة البيانات.