Mobius เป็นเฟรมเวิร์กเชิงโต้ตอบที่ใช้งานได้สำหรับจัดการวิวัฒนาการสถานะและผลข้างเคียง พร้อมด้วยส่วนเสริมสำหรับการเชื่อมต่อกับ Android UI และ RxJava Observables โดยเน้นการแยกข้อกังวล ความสามารถในการทดสอบ และการแยกส่วนที่มีสถานะของโค้ดออกจากกัน
หากต้องการเรียนรู้เพิ่มเติม โปรดไปที่เว็บไซต์เพื่อดูคู่มือผู้ใช้ หากต้องการดูการทำงานของ Mobius ให้ดูตัวอย่างแอป TODO ที่อิงตามแอปจากพิมพ์เขียวสถาปัตยกรรม Android คุณยังสามารถรับชมการพูดคุยจาก Android @Scale ที่แนะนำ Mobius
Mobius อยู่ในสถานะการผลิต ซึ่งหมายความว่าจะใช้ในการผลิตในแอปพลิเคชัน Spotify Android และเราถือว่า API มีความเสถียรและไม่มีข้อบกพร่องในการใช้งาน เราจะไม่ทำการเปลี่ยนแปลงที่ทำลายความเข้ากันได้แบบย้อนหลัง
ปัจจุบัน Mobius ถูกสร้างขึ้นสำหรับ Java 7 (เนื่องจาก Java 8 ไม่ได้รับการสนับสนุนอย่างสมบูรณ์บน Android ทุกเวอร์ชัน) ดังนั้นจึงมีความซ้ำซ้อนของแนวคิดบางอย่างที่กำหนดไว้ใน java.util.function
(ดู com.spotify.mobius.functions
)
เมื่อใช้ Mobius เราขอแนะนำให้ใช้ Kotlin หรือ Java 8 หรือใหม่กว่า สาเหตุหลักมาจากการอนุมานประเภทที่ได้รับการปรับปรุง และเนื่องจากการใช้ lambdas ช่วยปรับปรุงความสามารถในการอ่านและความกระชับของโค้ดได้อย่างมาก
Mobius เวอร์ชันล่าสุดมีให้บริการผ่าน Maven Central (LATEST_RELEASE ด้านล่างคือ ):
implementation ' com.spotify.mobius:mobius-core:LATEST_RELEASE '
testImplementation ' com.spotify.mobius:mobius-test:LATEST_RELEASE '
implementation ' com.spotify.mobius:mobius-rx:LATEST_RELEASE ' // only for RxJava 1 support
implementation ' com.spotify.mobius:mobius-rx2:LATEST_RELEASE ' // only for RxJava 2 support
implementation ' com.spotify.mobius:mobius-rx3:LATEST_RELEASE ' // only for RxJava 3 support
implementation ' com.spotify.mobius:mobius-android:LATEST_RELEASE ' // only for Android support
implementation ' com.spotify.mobius:mobius-extras:LATEST_RELEASE ' // utilities for common patterns
นี่คือแกนหลักของ Mobius ซึ่งโมดูลอื่นๆ ทั้งหมดต้องพึ่งพา เป็นไลบรารี Java ล้วนๆ ที่มีอยู่ในตัวเองโดยสมบูรณ์ นี่เป็นโมดูลเดียวที่คุณต้องการเมื่อใช้ Mobius เนื่องจากโมดูลอื่นๆ เป็นตัวเลือกส่วนขยายของแกนหลัก
โมดูลทดสอบประกอบด้วยยูทิลิตี้ที่ช่วยคุณเขียนการทดสอบสำหรับแอปพลิเคชัน Mobius ควรใช้เป็นการพึ่งพาการทดสอบเท่านั้น
โมดูล rx มีส่วนขยายสำหรับ RxJava คุณควรใช้หนึ่งในนั้นในแอปพลิเคชัน Mobius ของคุณ เนื่องจากจะทำให้การสร้างตัวจัดการเอฟเฟกต์และแหล่งที่มาของเหตุการณ์ง่ายขึ้น โมดูล RxJava ทั้งสองใช้ API เดียวกัน ข้อแตกต่างเพียงอย่างเดียวคือโมดูลหนึ่งสร้างขึ้นสำหรับ RxJava 1.x และอีกโมดูลสำหรับ RxJava 2.x
โมดูล android มีคลาสสำหรับเชื่อมต่อ MobiusLoop กับ Android เป็นหลัก
โมดูลพิเศษประกอบด้วยยูทิลิตี้และคลาสที่ช่วยลดรูปแบบการใช้งานขั้นสูงบางอย่าง (เช่น ฟังก์ชันการอัพเดตแบบซ้อน)
เป้าหมายของ Mobius คือเพื่อให้คุณควบคุมสถานะแอปพลิเคชันของคุณได้ดียิ่งขึ้น คุณสามารถนึกถึงสถานะของคุณเป็นภาพรวมของค่าปัจจุบันทั้งหมดของตัวแปรในแอปพลิเคชันของคุณ ใน Mobius เราสรุปสถานะทั้งหมดไว้ในโครงสร้างข้อมูลซึ่งเราเรียกว่า Model
โมเดล สามารถแสดงได้ตามประเภทที่คุณต้องการ ในตัวอย่างนี้ เราจะสร้างตัวนับแบบง่าย ดังนั้นสถานะทั้งหมดของเราจึงสามารถมีอยู่ใน Integer
:
Mobius ไม่อนุญาตให้คุณจัดการรัฐโดยตรง ในการเปลี่ยนสถานะ คุณต้องส่งข้อความกรอบงานเพื่อบอกว่าคุณต้องการทำอะไร เราเรียกข้อความเหล่านี้ ว่าเหตุการณ์ ในกรณีของเรา เราต้องการเพิ่มและลดตัวนับของเรา ลองใช้ enum
เพื่อกำหนดกรณีเหล่านี้:
enum CounterEvent {
INCREMENT ,
DECREMENT ,
}
ตอนนี้เรามี โมเดล และ กิจกรรม บางอย่างแล้ว เราจะต้องมอบชุดกฎให้ Mobius ซึ่งสามารถใช้เพื่ออัปเดตสถานะในนามของเรา เราทำสิ่งนี้โดยให้ฟังก์ชันแก่เฟรมเวิร์กซึ่งจะถูกเรียกตามลำดับกับทุก เหตุการณ์ ที่เข้ามาและ Model ล่าสุด เพื่อสร้าง Model ถัดไป:
class CounterLogic {
static Integer update ( Integer model , CounterEvent event ) {
switch ( event ) {
case INCREMENT : return model + 1 ;
case DECREMENT : return model - 1 ;
}
}
}
ด้วย Building Block เหล่านี้ เราสามารถเริ่มคิดถึงแอปพลิเคชันของเราว่าเป็นการเปลี่ยนผ่านระหว่างสถานะที่แยกจากกันเพื่อตอบสนองต่อเหตุการณ์ แต่เราเชื่อว่ายังมีชิ้นส่วนหนึ่งที่หายไปจากปริศนา นั่นคือผลข้างเคียงที่เกี่ยวข้องกับการเคลื่อนที่ระหว่างรัฐ ตัวอย่างเช่น การกดปุ่ม "รีเฟรช" อาจทำให้แอปพลิเคชันของเราอยู่ในสถานะ "กำลังโหลด" โดยมีผลข้างเคียงจากการดึงข้อมูลล่าสุดจากแบ็กเอนด์ของเราด้วย
ใน Mobius เราเหมาะที่จะเรียกผลข้างเคียงเหล่านี้ว่า Effects ในกรณีของตัวนับของเรา สมมติว่าเมื่อผู้ใช้พยายามลดค่าให้ต่ำกว่า 0 เราจะเล่นเอฟเฟกต์เสียงแทน มาสร้าง enum
ที่แสดงถึงเอฟเฟกต์ที่เป็นไปได้ทั้งหมด (ซึ่งในกรณีนี้มีเพียงอันเดียวเท่านั้น):
enum CounterEffect {
PLAY_SOUND ,
}
ตอนนี้เราจะต้องเพิ่มฟังก์ชัน update
ของเราเพื่อส่งคืนชุดเอฟเฟกต์ที่เกี่ยวข้องกับการเปลี่ยนสถานะบางอย่าง ในการดำเนินการนี้ เราจะใช้อินเทอร์เฟซ Update
ดังนี้:
class CounterLogic implements Update < Integer , CounterEvent , CounterEffect > {
public Next < Integer , CounterEffect > update ( Integer model , CounterEvent event ) {
switch ( event ) {
case INCREMENT :
return next ( model + 1 );
case DECREMENT :
if ( model == 0 ) {
Set < CounterEffect > soundEffect = effects ( CounterEffect . PLAY_SOUND );
return dispatch ( soundEffect );
}
return next ( model - 1 );
}
throw new IllegalStateException ( "Unhandled event: " + event );
}
}
Mobius จะส่งเอฟเฟกต์แต่ละอย่างที่คุณส่งคืนในการเปลี่ยนสถานะไปเป็นสิ่งที่เรียกว่า Effect Handler มาสร้างหนึ่งในนั้นตอนนี้โดยใช้อินเทอร์เฟซ Connectable
ต่อได้:
class CounterEffectHandler implements Connectable < CounterEffect , CounterEvent > {
public Connection < CounterEffect > connect ( Consumer < CounterEvent > output ) {
return new Connection < CounterEffect >() {
@ Override
public void accept ( CounterEffect effect ) {
if ( effect == CounterEffect . PLAY_SOUND ) {
Toolkit . getDefaultToolkit (). beep ();
}
}
@ Override
public void dispose () {}
};
}
}
เมื่อได้ชิ้นส่วนทั้งหมดเรียบร้อยแล้ว เรามาต่อทั้งหมดเข้าด้วยกัน:
public static void main ( String [] args ) {
// Let's make a Mobius Loop
MobiusLoop < Integer , CounterEvent , CounterEffect > loop = Mobius
. loop ( new CounterLogic (), new CounterEffectHandler ())
. startFrom ( 0 );
// And start using our loop
loop . dispatchEvent ( CounterEvent . INCREMENT ); // Model is now 1
loop . dispatchEvent ( CounterEvent . DECREMENT ); // Model is now 0
loop . dispatchEvent ( CounterEvent . DECREMENT ); // Sound effect plays! Model is still 0
}
ซึ่งครอบคลุมพื้นฐานของ Mobius หากต้องการเรียนรู้เพิ่มเติม ตรงไปที่เว็บไซต์ของเรา
เรากำลังใช้ตัวจัดรูปแบบอัตโนมัติของ Google เพื่อจัดรูปแบบโค้ด ไปป์ไลน์การสร้างได้รับการตั้งค่าให้ล้มเหลวในการสร้างที่จัดรูปแบบไม่ถูกต้อง เพื่อให้แน่ใจว่ามีการจัดรูปแบบที่ถูกต้อง ให้รัน
./gradlew format
โครงการนี้ปฏิบัติตามหลักจรรยาบรรณแบบเปิด ในการเข้าร่วม คุณจะต้องปฏิบัติตามรหัสนี้