ผู้ประกอบการใช้เพื่อแก้ปัญหาการเปลี่ยนวัตถุที่สังเกตได้ ผู้ประกอบการจะใช้ในการปรับเปลี่ยนเหตุการณ์ที่ปล่อยออกมาโดยสังเกตได้ระหว่างผู้ที่สังเกตได้และสมาชิกขั้นสุดท้าย RXJAVA ให้บริการที่มีประโยชน์มากมาย
ตัวอย่างเช่นตัวดำเนินการแผนที่ใช้เพื่อแปลงเหตุการณ์หนึ่งเป็นอีกเหตุการณ์หนึ่ง
สังเกตได้. Just ("สวัสดีโลก!") .map (ใหม่ func1 <สตริง, สตริง> () {@Override การเรียกสตริงสาธารณะ (สตริง s) {return s + "-dan";}}) .subscribe (s -> system.out.println (s)); การใช้แลมบ์ดาสามารถทำให้ง่ายขึ้น
สังเกตได้เพียงแค่ ("สวัสดีโลก!") .map (s -> s + "-dan") .subscribe (s -> system.out.println (s));มันไม่เจ๋งเหรอ? ตัวดำเนินการ MAP () ใช้เพื่อแปลงวัตถุที่สังเกตได้ ตัวดำเนินการแผนที่ส่งคืนวัตถุที่สังเกตได้เพื่อให้สามารถใช้การเรียกโซ่ได้และตัวดำเนินการแผนที่จะถูกใช้หลายครั้งในวัตถุที่สังเกตได้และในที่สุดข้อมูลที่ง่ายที่สุดจะถูกส่งผ่านไปยังวัตถุสมาชิก
ผู้ประกอบการแผนที่ขั้นสูง
สิ่งที่น่าสนใจมากขึ้นเกี่ยวกับผู้ประกอบการแผนที่คือไม่ต้องส่งคืนประเภทที่ส่งคืนโดยวัตถุที่สังเกตได้ คุณสามารถใช้ตัวดำเนินการแผนที่เพื่อส่งคืนวัตถุที่สังเกตได้ซึ่งปล่อยชนิดข้อมูลใหม่
ตัวอย่างเช่นในตัวอย่างข้างต้นสมาชิกไม่สนใจสตริงที่ส่งคืน แต่ต้องการค่าแฮชของสตริง
สังเกตได้. เพียงแค่ ("สวัสดีโลก!") .map (ใหม่ func1 <สตริง, จำนวนเต็ม> () {@Override การเรียกจำนวนเต็มสาธารณะ (สตริง s) {return s.hashCode ();}}). subscribe (i -> system.out.println (integer.tostring (i)); น่าสนใจมากใช่มั้ย การสังเกตเริ่มต้นของเราจะส่งคืนสตริงในขณะที่สมาชิกขั้นสุดท้ายได้รับจำนวนเต็ม แน่นอนว่าการใช้แลมบ์ดาสามารถทำให้รหัสง่ายขึ้น:
สังเกตได้เพียงแค่ ("สวัสดีโลก!") .map (s -> s.hashCode ()) .subscribe (i -> system.out.println (integer.toString (i))); ดังที่ได้กล่าวไว้ก่อนหน้านี้สิ่งที่น้อยกว่าที่สมัครเป็นสมาชิกทำได้ดีกว่า มาเพิ่มผู้ให้บริการแผนที่อื่น
สังเกตได้เพียงแค่ ("สวัสดีโลก!") .map (s -> s.hashCode ()) .map (i -> integer.toString (i)) .subscribe (s -> system.out.println (s)); ไม่เชื่อ?
คุณคิดว่าตัวอย่างของเราง่ายเกินไปที่จะโน้มน้าวคุณหรือไม่? คุณต้องเข้าใจสองประเด็นต่อไปนี้:
1. สังเกตได้และสมาชิกสามารถทำอะไรก็ได้
สามารถสังเกตได้สามารถเป็นแบบสอบถามฐานข้อมูลและสมาชิกใช้เพื่อแสดงผลลัพธ์การสืบค้น สามารถสังเกตได้อาจเป็นเหตุการณ์คลิกบนหน้าจอและสมาชิกใช้เพื่อตอบสนองต่อเหตุการณ์คลิก สามารถสังเกตได้อาจเป็นคำขอเครือข่ายและผู้สมัครสมาชิกจะใช้เพื่อแสดงผลการร้องขอ
2. สังเกตได้และสมาชิกเป็นอิสระจากกระบวนการแปลงขั้นกลาง
จำนวนแผนที่ใด ๆ สามารถเพิ่มหรือลดลงระหว่างที่สังเกตได้และสมาชิก ระบบทั้งหมดสามารถรวมกันได้สูงและข้อมูลการใช้งานเป็นกระบวนการที่ง่ายมาก
ตัวอย่าง
1. การเตรียม
สมมติว่าฉันมีวิธีการเช่นนี้:
วิธีนี้ส่งคืนรายการ URL ของเว็บไซต์ตามสตริงอินพุต (Ahha, Search Engine)
สังเกตได้ <list <String>> แบบสอบถาม (ข้อความสตริง);
ตอนนี้ฉันต้องการสร้างระบบที่แข็งแกร่งที่สามารถสอบถามสตริงและแสดงผลลัพธ์ได้ จากเนื้อหาของบล็อกก่อนหน้านี้เราอาจเขียนรหัสต่อไปนี้:
แบบสอบถาม ("สวัสดีโลก!") .subscribe (urls -> {for (string url: urls) {system.out.println (url);}});แน่นอนว่ารหัสประเภทนี้ไม่สามารถทนได้เนื่องจากรหัสข้างต้นทำให้เราสูญเสียความสามารถในการเปลี่ยนการไหลของข้อมูล เมื่อเราต้องการเปลี่ยน URL แต่ละรายการเราสามารถทำได้ในสมาชิกเท่านั้น เราไม่ได้ใช้ตัวดำเนินการ MAP () Cool! - -
แน่นอนฉันสามารถใช้ตัวดำเนินการแผนที่ อินพุตของแผนที่คือรายการ URL เมื่อการประมวลผลมันยังคงต้องสำรวจแต่ละครั้งซึ่งก็เจ็บปวดมาก
โชคดีที่มีวิธีการสังเกตจาก () ซึ่งได้รับการรวบรวมเป็นอินพุตแล้วส่งออกองค์ประกอบไปยังสมาชิกในแต่ละครั้ง:
สังเกตได้จาก ("url1", "url2", "url3") .subscribe (url -> system.out.println (url)); มาใช้วิธีนี้ในฉากนี้กันเถอะ:
แบบสอบถาม ("สวัสดีโลก!") .subscribe (urls -> {observable.from (urls) .subscribe (url -> system.out.println (url));});
แม้ว่าสำหรับแต่ละลูปจะถูกลบออก แต่รหัสก็ยังดูยุ่งเหยิง การสมัครสมาชิกที่ซ้อนกันหลายครั้งไม่เพียง แต่ดูน่าเกลียดและยากที่จะแก้ไข แต่อย่างจริงจังมากขึ้นเท่านั้นมันจะทำลายคุณสมบัติบางอย่างของ Rxjava ที่เรายังไม่ได้กล่าวถึง
2. การปรับปรุง
พระผู้ช่วยให้รอดอยู่ที่นี่เขาคือ Flatmap ()
สังเกตได้ FlatMap () ได้รับเอาต์พุตของสิ่งที่สังเกตได้ว่าเป็นอินพุตและเอาต์พุตที่สังเกตได้ในเวลาเดียวกัน ดูรหัสโดยตรง:
Query ("Hello, World!") .flatmap (ใหม่ func1 <list <string>, สังเกตได้ <String>> () {@Override สาธารณะสังเกตได้ <string> การโทร (รายการ <string> url) {return neverbable.from (urls);}}) .subscribe ที่นี่ฉันโพสต์รหัสฟังก์ชั่นทั้งหมดเพื่ออำนวยความสะดวกให้คุณเข้าใจว่าเกิดอะไรขึ้น การใช้แลมบ์ดาสามารถทำให้ความยาวรหัสง่ายขึ้นอย่างมาก:
แบบสอบถาม ("สวัสดีโลก!") .flatmap (urls -> สังเกตได้จาก (urls)) .subscribe (url -> system.out.println (url));FlatMap () ดูแปลก ๆ หรือไม่? ทำไมมันกลับมาสังเกตอีกครั้ง? จุดสำคัญในการทำความเข้าใจ FlatMap คือเอาต์พุตที่สังเกตได้ใหม่จาก FlatMap เป็นสิ่งที่เราต้องการรับในสมาชิก ตอนนี้สมาชิกไม่ได้รับรายการ <string> อีกต่อไป แต่แทนที่จะได้รับสตริงเดียวของคอลัมน์เดียวเช่นเดียวกับเอาต์พุตของ Observable. จาก ()
ส่วนนี้ยังเป็นส่วนที่ยากที่สุดเมื่อฉันเรียนรู้ Rxjava เป็นครั้งแรก เมื่อฉันรู้ทันทีคำถามหลายข้อใน Rxjava ได้รับการแก้ไข
3. มันจะดีกว่า
FlatMap () ไม่ใช่ความคิดที่ดีกว่าจริงๆมันสามารถส่งคืนวัตถุที่สังเกตได้ใด ๆ ที่ต้องการกลับมา
ตัวอย่างเช่นวิธีการต่อไปนี้:
// ส่งคืนชื่อของเว็บไซต์และหากเป็น 404 ให้ส่งคืนค่า null ที่สังเกตได้ <string> getTitle (url สตริง);
ตามตัวอย่างก่อนหน้านี้ตอนนี้ฉันไม่ต้องการพิมพ์ URL อีกต่อไป แต่พิมพ์ชื่อของแต่ละเว็บไซต์ที่ฉันได้รับแทน ปัญหาคือวิธีการของฉันสามารถผ่าน URL ได้ครั้งละหนึ่งครั้งเท่านั้นและค่าการส่งคืนไม่ใช่สตริง แต่เป็นวัตถุที่สังเกตได้ที่ส่งออกสตริง การใช้ FlatMap () สามารถแก้ปัญหานี้ได้
แบบสอบถาม ("สวัสดีโลก!") .flatmap (urls -> สังเกตได้จาก (urls)) .flatmap (func1 ใหม่ <สตริง, สังเกตได้ <String>> () {@Override สาธารณะที่สังเกตได้ 4. ใช้แลมบ์ดา:
แบบสอบถาม ("สวัสดีโลก!") .flatmap (urls -> สังเกตได้จาก (urls)) .flatmap (url -> gettitle (url)) .subscribe (ชื่อ -> system.out.println (ชื่อ)); มันไม่น่าเหลือเชื่อเหรอ? จริง ๆ แล้วฉันสามารถรวมวิธีการอิสระหลายวิธีเพื่อส่งคืนวัตถุที่สังเกตได้เข้าด้วยกัน! หล่อมาก!
ยิ่งไปกว่านั้นฉันยังรวมการโทรของ API สองครั้งในการโทรที่ถูกล่ามโซ่ เราสามารถเชื่อมโยงการโทร API ให้ได้มากที่สุด ทุกคนควรรู้ว่ามันเจ็บปวดแค่ไหนที่จะซิงโครไนซ์การโทร API ทั้งหมดแล้วรวมผลลัพธ์การโทรกลับของการโทร API ทั้งหมดลงในข้อมูลที่จะแสดง ที่นี่เราหลีกเลี่ยงการโทรกลับได้สำเร็จ ตอนนี้ตรรกะทั้งหมดถูกห่อหุ้มด้วยการโทรตอบสนองง่ายๆนี้
5. ผู้ให้บริการที่หลากหลาย <BR /> จนถึงตอนนี้เราได้ติดต่อกับผู้ให้บริการสองรายและมีผู้ให้บริการมากขึ้นใน RXJAVA ดังนั้นเราจะใช้ผู้ให้บริการรายอื่นเพื่อปรับปรุงรหัสของเราได้อย่างไร
getTitle () ส่งคืนค่า null หากไม่มี URL เราไม่ต้องการส่งออก "null" จากนั้นเราสามารถกรองค่า NULL จากรายการชื่อเรื่องที่ส่งคืน!
แบบสอบถาม ("สวัสดีโลก!") .flatmap (urls -> สังเกตได้จาก (urls)) .flatmap (url -> getTitle (url)) .filter (ชื่อ -> ชื่อ! = null) .subscribe (ชื่อ -> system.out.ตัวกรอง () ส่งออกองค์ประกอบเดียวกับอินพุตและกรองออกองค์ประกอบที่ไม่ตรงตามเกณฑ์การตรวจสอบ
หากเราต้องการเพียง 5 ผลลัพธ์:
แบบสอบถาม ("สวัสดีโลก!") .flatmap (urls -> สังเกตได้จาก (urls)) .flatmap (url -> gettitle (url)) .filter (ชื่อ -> ชื่อ! = null). take (5).ใช้ () เอาต์พุตจำนวนสูงสุดของผลลัพธ์
หากเราต้องการบันทึกแต่ละชื่อลงในดิสก์ก่อนพิมพ์:
แบบสอบถาม ("สวัสดีโลก!") .flatmap (urls -> สังเกตได้จาก (urls)) .flatmap (url -> gettitle (url)) .filter (ชื่อ -> ชื่อ! = null).doonnext () ช่วยให้เราสามารถทำสิ่งพิเศษบางอย่างก่อนที่จะส่งออกองค์ประกอบในแต่ละครั้งเช่นบันทึกชื่อที่นี่
ง่ายไหมที่จะเห็นว่ามันง่ายแค่ไหนในการใช้งานการไหลของข้อมูลที่นี่? คุณสามารถเพิ่มการดำเนินการได้มากเท่าที่คุณต้องการและไม่ทำให้รหัสของคุณยุ่งเหยิง
RXJAVA มีผู้ให้บริการจำนวนมาก จำนวนผู้ให้บริการค่อนข้างน่ากลัว แต่ก็คุ้มค่าที่จะตรวจสอบทีละคนเพื่อให้คุณสามารถรู้ได้ว่าผู้ให้บริการใดสามารถใช้งานได้ อาจต้องใช้เวลาพอสมควรในการเข้าใจผู้ประกอบการเหล่านี้ แต่เมื่อคุณเข้าใจคุณจะเข้าใจพลังของ Rxjava อย่างเต็มที่
คุณยังสามารถเขียนตัวดำเนินการที่กำหนดเองได้! บล็อกนี้ไม่ได้ตั้งใจที่จะปรับแต่งผู้ให้บริการ หากคุณต้องการโปรดใช้ Google ด้วยตัวคุณเอง
คุณรู้สึกอย่างไร?
คุณเป็นคนขี้ระแวงและยากที่จะโน้มน้าวใจดังนั้นทำไมคุณถึงสนใจเกี่ยวกับผู้ประกอบการเหล่านี้?
เพราะผู้ประกอบการอนุญาตให้คุณทำทุกอย่างเพื่อสตรีมข้อมูล
การเชื่อมโยงชุดของตัวดำเนินการสามารถบรรลุตรรกะที่ซับซ้อน รหัสถูกแบ่งออกเป็นชุดตัวอย่างที่สามารถรวมกันได้ นี่คือเสน่ห์ของการเขียนโปรแกรมฟังก์ชั่นปฏิกิริยา ยิ่งคุณใช้มันมากเท่าไหร่คุณก็จะเปลี่ยนความคิดการเขียนโปรแกรมของคุณมากขึ้นเท่านั้น
นอกจากนี้ Rxjava ยังช่วยให้เราประมวลผลข้อมูลได้ง่ายขึ้น ในตัวอย่างสุดท้ายเราเรียก API สองตัวประมวลผลข้อมูลที่ส่งคืนโดย API และบันทึกลงในดิสก์ แต่สมาชิกของเราไม่ทราบสิ่งนี้มันแค่คิดว่ามันได้รับวัตถุ <string> ที่สังเกตได้ บรรจุภัณฑ์ที่ดียังนำความสะดวกในการเขียนโค้ด!
ในส่วนที่สามฉันจะแนะนำคุณสมบัติที่ยอดเยี่ยมอื่น ๆ ของ RXJAVA เช่นการจัดการข้อผิดพลาดและการเกิดขึ้นพร้อมกันซึ่งไม่ได้ใช้โดยตรงในการประมวลผลข้อมูล