Fish Redux - Perpustakaan Redux Baru untuk Flutter

Pada akhir 2018, Google, dengan bantuan komunitas Open-Source, membuat hadiah luar biasa bagi pengembang seluler dengan merilis versi stabil pertama dari kerangka kerja pengembangan lintas-platform Flutter.


Namun, ketika mengembangkan aplikasi besar yang sedikit lebih besar dari Hello Worlds satu halaman, pengembang mungkin mengalami ketidakpastian. Bagaimana cara menulis aplikasi? Kerangka ini cukup muda, masih belum ada dasar yang cukup dari contoh-contoh bagus dengan sumber terbuka, yang didasarkan pada kemungkinan untuk memahami pro dan kontra menggunakan berbagai pola, untuk memahami apa yang harus digunakan dalam kasus khusus ini dan apa yang tidak.


Situasi ini diselamatkan oleh fakta bahwa Flutter memiliki tingkat kemiripan dengan React and React Native, yang artinya Anda dapat belajar dari beberapa pengalaman pemrograman di Flutter. Mungkin karena inilah perpustakaan seperti Flutter Flux , Flutter Hooks , MobX , serta beberapa implementasi Redux muncul sekaligus. Untuk waktu yang lama, versi yang paling populer adalah Brian Egan bernama Flutter Redux .


Namun, beberapa bulan yang lalu komit pertama dilihat oleh perpustakaan Fish Redux , diterbitkan dengan nama Alibaba. Perpustakaan dalam waktu singkat mendapatkan popularitas besar, sudah pada hari pertama sebelum implementasi Brian dalam hal jumlah bintang, dan pada hari kedua itu dua kali lebih cepat.


Terlepas dari popularitasnya, Fish memiliki masalah dengan dokumentasi, yang sebagian besar memberikan deskripsi kelas yang ada dengan beberapa contoh singkat. Lebih buruk lagi, beberapa dokumentasi hanya tersedia dalam bahasa Cina. Ada kesulitan lain: hampir tidak ada masalah berbahasa Inggris, jadi mengandalkan pengalaman dari pengembang lain sangat sulit, yang sangat kritis, mengingat hanya versi pratinjau pertama yang dirilis.


Jadi apa perbedaan yang signifikan antara versi Fish'a dari Brian? Flutter Redux adalah kerangka kerja manajemen negara. Fish adalah kerangka kerja aplikasi yang menempatkan Redux di pusatnya sebagai dasar untuk manajemen negara. Yaitu Ikan menyelesaikan beberapa tugas lagi dan tidak terbatas pada state management .


Salah satu fitur utama dari Fish Redux adalah penyatuan beberapa reduksi menjadi yang lebih besar melalui ekspresi langsung dari hubungan di antara mereka, ketika Redux reguler tidak memberikan kesempatan seperti itu sama sekali, memaksa pengembang untuk mengimplementasikan semuanya sendiri. Tapi mari kita kembali ke ini nanti, setelah berurusan dengan apa peredam ini, serta Fish Redux itu sendiri.


Hubungan antara Peredam, Efek dan Tampilan di Komponen


gambar


Dasar dari semua yang ada di Fish Redux adalah Component. Ini adalah objek yang terdiri dari tiga bagian: Efek, Peredam, dan Tampilan. Perlu dicatat bahwa hanya View, yaitu Efek dan Peredam adalah opsional, komponen dapat bekerja tanpanya. Komponen juga memiliki status saat ini.

Negara


Misalnya, ambil clicker. Biarkan hanya ada satu bidang di negara bagiannya - hitungan, yang akan menunjukkan jumlah klik sempurna.


 class ClickerState implements Cloneable<ClickerState> { int count = 0; @override ClickerState clone() { return ClickerState() ..count = count; } } 

Negara harus abadi, tidak berubah. Kekebalan negara dapat dengan mudah dipertahankan dengan mengimplementasikan antarmuka Cloneable. Di masa mendatang, saat Anda perlu membuat status baru, Anda cukup menggunakan metode clone() .


Peredam


Inti dari peredam adalah untuk merespons beberapa tindakan dengan mengembalikan negara baru. Peredam tidak boleh menimbulkan efek samping apa pun.


Kami akan menulis peredam sederhana yang akan menambah jumlah beberapa nomor setelah menerima Tindakan terkait (sedikit lebih rendah).


 ClickerState clickerReducer(ClickerState state, Action action) { //        Action,      . if (action.type == Actions.increase) { // ..       ,   ,       Count. return state.clone() ..count = state.count + action.payload; //        /payload/ count. // payload   . } // if (action.type == ...) { ... } //        . return state; } 

Juga, peredam ini dapat ditulis dalam bentuk berikut:


 Reducer<ClickerState> buildClickerReducer() { asReducer({ Actions.increase: (state, action) => state.clone() ..count = state.count + action.payload, //Actions.anotherAction: ... }); } 

Aksi


Aksi - kelas di perpustakaan FishRedux yang berisi dua bidang:
Object type - Object type tindakan, biasanya objek enum
dynamic payload - parameter tindakan, opsional.


Contoh:


 enum Actions { increase } //     class ActionsCreate { //      static Action increase(int value) => Action(Actions.increase, payload: value); } 

Lihat


Logikanya sudah siap, masih untuk menampilkan hasilnya. View adalah fungsi yang mengambil parameter keadaan saat ini, pengiriman, ViewService, dan mengembalikan Widget.


Fungsi pengiriman diperlukan untuk mengirim tindakan: tindakan, pembuatan yang kami jelaskan sebelumnya.
ViewService berisi BuildContext saat ini (dari library flutter standar) dan menyediakan metode untuk membuat dependensi, tetapi tentangnya nanti.


Contoh:


 Widget clickerView(ClickerState state, Dispatch dispatch, ViewService viewService) { return RaisedButton( child: Text(state.count.toString()), onPressed: () => dispatch(ActionsCreate.increase(1)) //         ); } 

Komponen


Kami akan mengumpulkan komponen kami dari semua ini:


 class ClickerComponent extends Component<ClickerState> { ClickerComponent() : super( reducer: clickerReducer, view: clickerView, ); } 

Seperti yang Anda lihat, efek tidak digunakan dalam contoh kita, karena itu tidak perlu. Efek adalah fungsi yang harus melakukan semua efek samping. Tapi mari kita datang dengan sebuah kasus di mana Anda tidak dapat melakukannya tanpa Efek. Misalnya, ini bisa berupa peningkatan dalam hitungan kami dengan nomor acak dari random.org.


Contoh penerapan efek
 import 'package:http/http.dart' as http; //   http   Effect<ClickerState> clickerEffect() { return combineEffects({ Actions.increaseRandomly: increaseRandomly, }); } Future<void> increaseRandomly(Action action, Context<ClickerState> context) async { final response = await http.read('https://www.random.org/integers/?num=1&min=1&max=10&col=1&base=10&format=plain'); //   random.org.      1  10. final value = int.parse(response); context.dispatch(ActionsCreate.increase(value)); } //   increaseRandomly enum Actions { increase, /* new */ increaseRandomly } class ActionsCreate { static Action increase(int value) => Action(Actions.increase, payload: value); static Action increaseRandomly() => const Action(Actions.increaseRandomly); // new } //  ,        . Widget clickerView(ClickerState state, Dispatch dispatch, ViewService viewService) { return Column( mainAxisSize: MainAxisSize.min, children: [ RaisedButton( //   child: Text(state.count.toString()), onPressed: () => dispatch(ActionsCreate.increase(1)) ), RaisedButton( //  child: const Text('Increase randomly'), onPressed: () => dispatch(ActionsCreate.increaseRandomly()) ), ] ); } //     class ClickerComponent extends Component<ClickerState> { ClickerComponent() : super( reducer: clickerReducer, view: clickerView, effect: clickerEffect() ); } 

Halaman


Ada ekstensi untuk Komponen yang disebut Halaman <T, P>. Halaman ini mencakup dua bidang tambahan:
T initState(P params) - fungsi yang mengembalikan status awal. Akan dipanggil saat halaman dibuat.
List<Middleware<T>> middleware - daftar Middleware - fungsi yang akan dipanggil sebelum reducer.
Dan juga satu metode:
Widget buildPage(P params) - yang mengumpulkan halaman menjadi widget yang berfungsi.


Mari kita buat halaman utama aplikasi:


 class MainPage extends Page<void, void> { MainPage(): super( initState: (dynamic param) {}, view: (state, dispatch, viewService) => Container(), ); } 

Halaman memperluas komponen, yang berarti dapat menyertakan peredam, efek, dan segala sesuatu yang dimiliki komponen biasa.


Dalam contoh tersebut, halaman kosong dibuat yang tidak memiliki status, atau reduksi atau efek. Kami akan memperbaikinya nanti.


Semua ini dalam bentuk yang sedikit berbeda dan dalam Flutter Redux karya Brian Egan, serta implementasi Redux lainnya. Mari kita beralih ke fitur utama perpustakaan baru - dependensi.


Ketergantungan


Fish Redux mengharuskan Anda untuk secara eksplisit mendefinisikan dependensi antar komponen. Jika Anda ingin menggunakan subkomponen dalam komponen, Anda tidak hanya perlu menulis dua komponen ini, tetapi juga membuat konektor yang akan bertanggung jawab untuk mengubah satu keadaan ke keadaan lain. Misalkan kita ingin menanamkan ClickerComponent di halaman MainPage.


Pertama, Anda perlu menambahkan status ke halaman kami:


 class MainState implements Cloneable<MainState> { ClickerState clicker; @override MainState clone() { return MainState() ..clicker = clicker; } static MainState initState(dynamic params) { return MainState() ..clicker = ClickerState(); } } 

Sekarang kita dapat menulis Connector:


 class ClickerConnector extends ConnOp<MainState, ClickerState> { @override ClickerState get(MainState state) => state.clicker; //        . @override void set(MainState state, ClickerState subState) => state.clicker = subState; } 

Itu saja. Semuanya siap untuk menambahkan komponen kami:


 class MainPage extends Page<MainState, void> { MainPage(): super( initState: MainState.initState, dependencies: Dependencies( slots: { 'clicker': ClickerComponent().asDependent(ClickerConnector()), //    // 'clicker': ClickerComponent() + ClickerConnector(), }, ), view: (state, dispatch, viewService) { //   clicker-. final clickerWidget = viewService.buildComponent('clicker'); return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [ Center( child: clickerWidget, //   ) ], ) ); }, ); } 

Dengan demikian, sekarang Anda dapat membangun aplikasi yang berfungsi lengkap dengan menambahkan kode berikut ke main.dart :


 void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) => MaterialApp(home: MainPage().buildPage(null)); } 

Semua kode yang dipisahkan file tersedia di sini . Memiliki pengalaman pengembangan yang baik dengan Flutter.

Source: https://habr.com/ru/post/id450586/


All Articles