Kami menulis aplikasi di Flutter bersama dengan Redux

gambar


Halo semuanya! Pada artikel ini, saya ingin menunjukkan kepada Anda cara membuat aplikasi Flutter menggunakan Redux. Jika Anda tidak tahu apa itu Flutter , maka ini adalah SDK open source untuk membuat aplikasi seluler dari Google. Ini digunakan untuk mengembangkan aplikasi untuk Android dan iOS, dan itu juga satu-satunya cara untuk mengembangkan aplikasi untuk Google Fuchsia.

Jika Anda terbiasa dengan Flutter dan ingin membuat aplikasi yang dirancang dengan baik, mudah diuji, dan memiliki perilaku yang sangat mudah ditebak, lanjutkan membaca artikel ini dan Anda akan segera mengetahuinya!

Tetapi sebelum kita mulai menulis aplikasi itu sendiri. Mari kita sedikit berkenalan dengan teori, mari kita mulai dengan menjelaskan apa itu Redux.

Apa itu Redux?


Redux adalah arsitektur yang awalnya dibuat untuk bahasa JavaScript dan digunakan dalam aplikasi yang dibuat menggunakan kerangka kerja reaktif (seperti React Native atau Flutter). Redux adalah versi sederhana dari arsitektur Flux yang dibuat oleh Facebook. Intinya, Anda perlu tahu tiga hal:

  1. Satu-satunya sumber kebenaran - seluruh keadaan aplikasi Anda disimpan hanya di satu tempat (disebut store ).
  2. state read-only / state read-only - untuk mengubah status aplikasi, Anda perlu mengirim tindakan (action), setelah itu negara baru akan dibuat
  3. perubahan dibuat menggunakan fungsi murni / fungsi murni - fungsi murni (untuk kesederhanaan, itu adalah fungsi tanpa efek samping) mengambil aplikasi keadaan saat ini dan tindakan dan mengembalikan keadaan aplikasi yang baru

Catatan: Efek samping dari fungsi adalah kemampuan, dalam proses melakukan perhitungannya: untuk membaca dan memodifikasi nilai-nilai variabel global, melaksanakan operasi I / O, merespons situasi luar biasa, dan memanggil penangannya. Jika Anda memanggil fungsi dengan efek samping dua kali dengan set nilai argumen input yang sama, mungkin terjadi bahwa nilai yang berbeda dikembalikan sebagai hasilnya. Fungsi tersebut disebut fungsi non-deterministik dengan efek samping.

Kedengarannya keren, tetapi apa manfaat dari solusi ini?

  • kami memiliki kontrol atas negara / negara bagian - ini berarti bahwa kami tahu persis apa yang menyebabkan perubahan keadaan, kami tidak memiliki status rangkap, dan kami dapat dengan mudah memantau aliran data
  • Peredam adalah fungsi murni yang mudah diuji - kita dapat melewati status, bertindak ke input dan memeriksa apakah hasilnya benar
  • Aplikasi terstruktur dengan jelas - kami memiliki lapisan yang berbeda untuk tindakan, model, logika bisnis, dll. - sehingga Anda tahu persis di mana menambahkan fitur baru lainnya
  • ini adalah arsitektur yang hebat untuk aplikasi yang lebih kompleks - Anda tidak perlu memberikan status melintasi seluruh pohon pandangan Anda dari orangtua ke anak
  • dan ada satu lagi ...

Perjalanan waktu redux


Redux memiliki satu peluang menarik - Perjalanan Waktu! Dengan Redux dan alat terkait, Anda dapat melacak keadaan aplikasi Anda dari waktu ke waktu, memeriksa keadaan sebenarnya dan membuatnya kembali kapan saja. Lihat fitur ini dalam aksi:

gambar

Widget Redux dengan Contoh Sederhana


Semua aturan di atas membuat aliran data di Redux searah. Tapi apa artinya itu? Dalam praktiknya, semua ini dilakukan dengan menggunakan tindakan , reduksi , penyimpanan , dan status . Mari kita bayangkan aplikasi yang menampilkan penghitung:

gambar

  1. Aplikasi Anda memiliki status tertentu saat startup (jumlah klik, yaitu 0)
  2. Berdasarkan kondisi ini, tampilan diberikan.
  3. Jika pengguna mengklik tombol, tindakan dikirim (misalnya, IncrementCounter)
  4. Setelah itu, tindakan menerima peredam yang mengetahui keadaan sebelumnya (penghitung 0), dan menerima tindakan (IncrementCounter) dan dapat mengembalikan keadaan baru (penghitung sekarang 1)
  5. Aplikasi kami memiliki status baru (penghitung adalah 1)
  6. Berdasarkan status baru, tampilan digambar ulang, yang menampilkan status saat ini

Jadi, seperti yang Anda lihat, biasanya ini semua tentang keadaan . Anda memiliki satu status dari keseluruhan aplikasi, status hanya-baca , dan untuk membuat status baru Anda perlu mengirim tindakan . Tindakan pengajuan meluncurkan peredam , yang menciptakan dan mengembalikan kepada kami keadaan baru. Dan ceritanya berulang.

gambar

Mari kita membuat aplikasi kecil dan mengenal implementasi pendekatan Redux dalam aksi, aplikasi akan disebut " Daftar Belanja "

Kita akan melihat bagaimana Redux bekerja dalam praktiknya. Kami akan membuat aplikasi ShoppingCart sederhana. Aplikasi akan memiliki fitur-fitur seperti:

  • menambahkan pembelian
  • Anda dapat menandai pembelian sebagai selesai
  • dan itu pada dasarnya semua

Aplikasi akan terlihat seperti ini:

gambar

Mari kita mulai menulis kode!

Prasyarat


Pada artikel ini, saya tidak akan menunjukkan pembuatan antarmuka pengguna untuk aplikasi ini. Anda dapat membiasakan diri dengan kode yang saya siapkan untuk Anda sebelum melanjutkan dengan penyelaman Redux . Setelah itu kami akan terus menulis kode dan menambahkan Redux ke aplikasi saat ini.

Catatan: Jika Anda belum pernah menggunakan Flutter sebelumnya, saya sarankan Anda mencoba Flutter Codelabs dari Google .

Persiapan awal


Untuk mulai menggunakan Redux untuk Flutter, kita perlu menambahkan dependensi ke file pubspec.yaml :

flutter_redux: ^0.5.2 

Anda juga dapat memeriksa versi dependensi ini dengan membuka halaman flutter_redux .

Pada saat penulisan, versinya adalah, flutter_redux 0.6.0

Model


Aplikasi kita harus bisa mengendalikan penambahan dan modifikasi elemen, jadi kita akan menggunakan model CartItem sederhana untuk menyimpan status satu elemen. Semua status aplikasi kita hanya akan menjadi daftar CartItems. Seperti yang Anda lihat, CartItem hanyalah sebuah objek.

 class CartItem { String name; bool checked; CartItem(this.name, this.checked); } 

Pertama, kita perlu menyatakan tindakan. Sebenarnya, tindakan adalah segala niat yang dapat digunakan untuk mengubah status aplikasi. Intinya, akan ada dua tindakan untuk menambah dan mengubah elemen:

 class AddItemAction { final CartItem item; AddItemAction(this.item); } class ToggleItemStateAction { final CartItem item; ToggleItemStateAction(this.item); } 

Maka kita perlu memberi tahu aplikasi kita apa yang harus dilakukan dengan tindakan ini. Itu sebabnya reduksi digunakan - mereka hanya mengambil status aplikasi saat ini dan tindakan (status aplikasi dan tindakan), lalu membuat dan mengembalikan status baru. Kami akan memiliki dua metode peredam :

 List<CartItem> appReducers(List<CartItem> items, dynamic action) { if (action is AddItemAction) { return addItem(items, action); } else if (action is ToggleItemStateAction) { return toggleItemState(items, action); } return items; } List<CartItem> addItem(List<CartItem> items, AddItemAction action) { return List.from(items)..add(action.item); } List<CartItem> toggleItemState(List<CartItem> items, ToggleItemStateAction action) { return items.map((item) => item.name == action.item.name ? action.item : item).toList(); } 

Metode appReducers () mendelegasikan tindakan ke metode yang sesuai. Kedua metode addItem () dan toggleItemState () mengembalikan daftar baru - ini adalah keadaan / keadaan baru kita. Seperti yang Anda lihat, Anda tidak boleh mengubah daftar saat ini . Sebagai gantinya, kami membuat daftar baru setiap kali.

StoreProvider


Sekarang kita memiliki tindakan dan reduksi , kita perlu menyediakan tempat untuk menyimpan status aplikasi . Di Redux, ini disebut toko dan satu-satunya sumber kebenaran untuk aplikasi tersebut.

 void main() { final store = new Store<List<CartItem>>( appReducers, initialState: new List()); runApp(new FlutterReduxApp(store)); } 

Untuk membuat toko , kita harus melewati metode reduksi dan status awal. Jika kami membuat toko , kami harus meneruskannya ke StoreProvider untuk memberi tahu aplikasi kami bahwa toko itu dapat digunakan oleh siapa saja yang ingin meminta status aplikasi saat ini.

 class FlutterReduxApp extends StatelessWidget { final Store<List<CartItem>> store; FlutterReduxApp(this.store); @override Widget build(BuildContext context) { return new StoreProvider<List<CartItem>>( store: store, child: new ShoppingCartApp(), ); } } 

Dalam contoh di atas, ShoppingCartApp ( ) adalah widget utama aplikasi kita.

StoreConnector


Saat ini kami memiliki semuanya kecuali ... benar-benar menambahkan dan mengubah item untuk dibeli. Bagaimana cara melakukannya? Untuk memungkinkan ini, kita perlu menggunakan StoreConnector . Ini adalah cara untuk mendapatkan toko dan mengirimkannya beberapa tindakan atau hanya mendapatkan kondisi saat ini.

Pertama, kami ingin mendapatkan data saat ini dan menampilkannya sebagai daftar di layar:

 class ShoppingList extends StatelessWidget { @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, List<CartItem>>( converter: (store) => store.state, builder: (context, list) { return new ListView.builder( itemCount: list.length, itemBuilder: (context, position) => new ShoppingListItem(list[position])); }, ); } } 

Kode di atas membungkus ListView.builder dengan StoreConnector . StoreConnector dapat menerima keadaan saat ini (yang merupakan daftar item ) dan dengan bantuan fungsi peta kita dapat mengubahnya menjadi apa pun. Tetapi dalam kasus kami itu akan menjadi negara yang sama (Daftar), karena di sini kita membutuhkan daftar belanja.

Selanjutnya, dalam fungsi builder , kita mendapatkan daftar - yang pada dasarnya adalah daftar CartItems dari toko , yang dapat kita gunakan untuk membuat ListView .

Oke, keren - kami punya data. Sekarang, bagaimana cara mengatur beberapa data?

Untuk ini, kami juga akan menggunakan StoreConnector , tetapi dengan cara yang sedikit berbeda.

 class AddItemDialog extends StatelessWidget { @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, OnItemAddedCallback>( converter: (store) { return (itemName) => store.dispatch(AddItemAction(CartItem(itemName, false))); }, builder: (context, callback) { return new AddItemDialogWidget(callback); }); } }typedef OnItemAddedCallback = Function(String itemName); 

Mari kita lihat kodenya. Kami menggunakan StoreConnector , seperti pada contoh sebelumnya, tetapi kali ini, alih-alih mencocokkan daftar CartItems dengan daftar yang sama, kami akan melakukan konversi menggunakan peta ke OnItemAddedCallback . Dengan demikian, kita dapat meneruskan fungsi panggilan balik ke AddItemDialogWidget dan menyebutnya ketika pengguna menambahkan elemen baru:

 class AddItemDialogWidgetState extends State<AddItemDialogWidget> { String itemName; final OnItemAddedCallback callback; AddItemDialogWidgetState(this.callback); @override Widget build(BuildContext context) { return new AlertDialog( ... actions: <Widget>[ ... new FlatButton( child: const Text('ADD'), onPressed: () { ... callback(itemName); }) ], ); } } 

Sekarang setiap kali pengguna mengklik tombol ADD, fungsi callback mengirimkan tindakan AddItemAction () .

Sekarang kita dapat membuat implementasi yang sangat mirip untuk mengubah keadaan elemen.

 class ShoppingListItem extends StatelessWidget { final CartItem item; ShoppingListItem(this.item); @override Widget build(BuildContext context) { return new StoreConnector<List<CartItem>, OnStateChanged>( converter: (store) { return (item) => store.dispatch(ToggleItemStateAction(item)); }, builder: (context, callback) { return new ListTile( title: new Text(item.name), leading: new Checkbox( value: item.checked, onChanged: (bool newValue) { callback(CartItem(item.name, newValue)); }), ); }); } } 

Seperti pada contoh sebelumnya, kami menggunakan StoreConnector untuk menampilkan Daftar untuk fungsi panggilan balik OnStateChanged . Sekarang setiap kali flag berubah (dalam metode onChanged), fungsi callback memecat event ToggleItemStateAction .

Ringkasan


Itu saja! Pada artikel ini, kami membuat aplikasi sederhana yang menampilkan daftar belanja dan sedikit terbenam dalam menggunakan arsitektur Redux. Dalam aplikasi kita, kita dapat menambahkan elemen dan mengubah kondisinya. Menambahkan fitur baru ke aplikasi ini semudah menambahkan tindakan dan reduksi baru .

Di sini Anda dapat menemukan kode sumber aplikasi ini, termasuk widget Time Travel :

Semoga Anda menikmati posting ini!

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


All Articles