Mobius adalah kerangka kerja reaktif fungsional untuk mengelola evolusi keadaan dan efek samping, dengan add-on untuk menghubungkan ke UI Android dan RxJava Observables. Ini menekankan pemisahan perhatian, kemampuan pengujian, dan mengisolasi bagian-bagian kode yang bersifat stateful.
Untuk mempelajari lebih lanjut, kunjungi situs web untuk panduan pengguna. Untuk melihat Mobius beraksi, lihat contoh aplikasi TODO berdasarkan aplikasi dari Cetak Biru Arsitektur Android. Anda juga dapat menonton pembicaraan dari Android @Scale yang memperkenalkan Mobius.
Mobius berstatus Produksi, artinya digunakan dalam produksi di aplikasi Spotify Android, dan kami menganggap API-nya stabil dan implementasinya bebas bug. Kami tidak akan melakukan perubahan yang dapat mengganggu kompatibilitas ke belakang.
Mobius saat ini dibuat untuk Java 7 (karena Java 8 tidak sepenuhnya didukung di semua versi Android), sehingga terjadi duplikasi beberapa konsep yang didefinisikan dalam java.util.function
(lihat com.spotify.mobius.functions
).
Saat menggunakan Mobius, kami merekomendasikan penggunaan Kotlin atau Java 8 atau yang lebih baru, terutama karena inferensi tipe yang lebih baik dan karena penggunaan lambda sangat meningkatkan keterbacaan dan keringkasan kode.
Versi terbaru Mobius tersedia melalui Maven Central (LATEST_RELEASE di bawah adalah ):
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
Ini adalah inti dari Mobius, yang menjadi sandaran semua modul lainnya. Ini adalah perpustakaan Java murni yang sepenuhnya mandiri. Ini adalah satu-satunya modul yang Anda perlukan saat menggunakan Mobius, karena modul lainnya merupakan ekstensi opsional pada intinya.
Modul pengujian berisi utilitas yang membantu Anda menulis pengujian untuk aplikasi Mobius. Ini hanya boleh digunakan sebagai ketergantungan pengujian.
Modul rx berisi ekstensi untuk RxJava. Anda harus menggunakan salah satunya di aplikasi Mobius Anda karena mereka menyederhanakan pembuatan penangan efek dan sumber kejadian. Kedua modul RxJava berbagi API yang sama, satu-satunya perbedaan adalah yang satu dibuat untuk RxJava 1.x dan yang lainnya untuk RxJava 2.x.
Modul android terutama berisi kelas-kelas untuk menghubungkan MobiusLoop ke Android.
Modul ekstra berisi utilitas dan kelas yang membantu mengurangi boilerplate untuk beberapa pola penggunaan lebih lanjut (misalnya, fungsi pembaruan bersarang).
Tujuan Mobius adalah memberi Anda kendali yang lebih baik atas status aplikasi Anda. Anda dapat menganggap status Anda sebagai cuplikan dari semua nilai variabel saat ini dalam aplikasi Anda. Di Mobius, kami merangkum semua status dalam struktur data yang kami sebut Model .
Model dapat diwakili oleh tipe apa pun yang Anda suka. Dalam contoh ini kita akan membuat counter sederhana, sehingga seluruh state kita dapat ditampung dalam Integer
:
Mobius tidak membiarkan Anda memanipulasi negara secara langsung. Untuk mengubah keadaan, Anda harus mengirimkan pesan kerangka kerja yang mengatakan apa yang ingin Anda lakukan. Kami menyebut pesan-pesan ini Peristiwa . Dalam kasus kami, kami ingin menambah dan mengurangi penghitung kami. Mari gunakan enum
untuk mendefinisikan kasus-kasus ini:
enum CounterEvent {
INCREMENT ,
DECREMENT ,
}
Sekarang kita memiliki Model dan beberapa Event , kita perlu memberi Mobius seperangkat aturan yang dapat digunakan untuk memperbarui status atas nama kita. Kita melakukan ini dengan memberikan kerangka sebuah fungsi yang akan dipanggil secara berurutan dengan setiap Event masuk dan Model terbaru, untuk menghasilkan Model berikutnya:
class CounterLogic {
static Integer update ( Integer model , CounterEvent event ) {
switch ( event ) {
case INCREMENT : return model + 1 ;
case DECREMENT : return model - 1 ;
}
}
}
Dengan elemen penyusun ini, kita dapat mulai menganggap aplikasi kita sebagai transisi antar keadaan terpisah sebagai respons terhadap peristiwa. Namun kami yakin masih ada satu bagian yang hilang dari teka-teki ini - yaitu efek samping yang terkait dengan perpindahan antar negara bagian. Misalnya, menekan tombol "segarkan" mungkin membuat aplikasi kita berada dalam status "memuat", dengan efek samping berupa pengambilan data terbaru dari backend kita.
Di Mobius, kami dengan tepat menyebut efek samping ini sebagai Effect s. Dalam kasus penghitung kita, katakanlah ketika pengguna mencoba mengurangi di bawah 0, kita malah memainkan efek suara. Mari kita buat enum
yang mewakili semua efek yang mungkin terjadi (yang dalam hal ini hanya satu):
enum CounterEffect {
PLAY_SOUND ,
}
Sekarang kita perlu menambah fungsi update
untuk mengembalikan serangkaian efek yang terkait dengan transisi keadaan tertentu. Untuk melakukan ini kami akan mengimplementasikan antarmuka Update
seperti:
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 mengirimkan setiap efek yang Anda kembalikan dalam transisi keadaan apa pun ke sesuatu yang disebut Effect Handler . Mari kita buat salah satunya sekarang dengan mengimplementasikan antarmuka 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 () {}
};
}
}
Sekarang kita sudah menyiapkan semua bagiannya, mari kita satukan semuanya:
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
}
Ini mencakup dasar-dasar Mobius. Untuk mempelajari lebih lanjut, kunjungi situs web kami.
Kami menggunakan pemformat otomatis Google untuk memformat kode. Alur build disiapkan untuk build gagal yang tidak diformat dengan benar. Untuk memastikan pemformatan yang benar, jalankan
./gradlew format
Proyek ini mematuhi Kode Etik Terbuka. Dengan berpartisipasi, Anda diharapkan menghormati kode ini.