
Pertama-tama, mari kita bicara sedikit tentang apa itu Flutter. Ini adalah kerangka kerja untuk membuat aplikasi seluler dari Google. Ini adalah lintas-platform dan memungkinkan Anda untuk mengkompilasi proyek yang dibuat untuk 3 sistem operasi:
Apalagi untuk OS terbaru - Fuchsia - ini adalah satu-satunya cara untuk membuat aplikasi.
Flutter untuk waktu yang lama, sejak 2015, hanya disajikan dalam versi alfa dan beta. Versi stabil pertama dirilis pada 4 Desember 2018.
Flutter secara aktif dipromosikan oleh Google, secara bertahap mendapatkan popularitas dan, kemungkinan besar, akan terus mengeluarkan alat pengembangan lintas-platform lain yang sedang digunakan (React Native, Xamarin), terutama jika Fuchsia didistribusikan secara luas. Mengingat Google memposisikan sistem operasi ini sebagai pengganti Android, cepat atau lambat Flutter akan menggantikan pengembangan Android asli. Karena itu, prospek dan pengembangan aktif adalah keunggulan utama Flutter.
+ Perspektif dan pengembangan aktif
Mari kita lihat cara kerjanya.
Dalam bahasa pemrograman Dart, aplikasi seluler dibuat dengan deskripsi antarmuka grafis dan seluruh logika kerja. Hasil karya ditambahkan ke aplikasi asli, seperti gambar, font dan sejenisnya (tentu saja, proses ini otomatis).
Pada saat yang sama, di bagian asli aplikasi, satu layar dibuat di mana mesin virtual Dart dimuat, yang menjalankan Flutter.
Perhatikan bahwa salah satu minus Flutter mengikuti dari sini:
- Paket instalasi akhir lebih besar, karena mesin virtual Dart ditambahkan ke dalamnya.
Dengan demikian, ada file Flutter dan ada mesin virtual yang ditambahkan tergantung pada kompilasi apa - iOS atau Android.
Mesin virtual memiliki mesin grafis sendiri, menggambar antarmuka aplikasi dengan semua transisi antara layar, dialog, fragmen, dll. Dalam hal ini, pengembangan di bawah Flutter sangat berbeda dari pengembangan dengan Xamarin dan React Native, yang menggunakan komponen Android dan iOS nyata. Dalam kasus mereka, tidak mungkin untuk menggunakan komponen spesifik platform (jika ada kebutuhan seperti itu, Anda harus membuat dua versi UI). Saat memilih desain dengan Flutter, cukup untuk fokus pada satu platform (misalnya, Android). Saat membangun proyek untuk iOS, Anda akan melihat antarmuka Android standar. Ini akan terlihat sedikit aneh dan tidak terduga, tetapi cukup fungsional (nantinya antarmuka dapat ditingkatkan).
+ Mesin grafis sendiri (tidak perlu membuat antarmuka secara terpisah untuk Android dan iOS)
Sekarang tentang tayangan.
Saat porting beberapa aplikasi dari Android ke Flutter, kami mencatat beberapa perbedaan, yang dapat dianggap sebagai plus dan minus.
Hal pertama yang menarik perhatian Anda adalah cara membuat layar, yang secara signifikan berbeda dari yang digunakan pada Android dan iOS. Di Android, logika dan antarmuka dipisahkan: logika diatur oleh kode, dan antarmuka diatur oleh tata letak di xml. Pada Flutter, ini semua diatur menggunakan kode. Meskipun di sini gaya khusus digunakan untuk antarmuka - elemen antarmuka dibuat bersarang satu sama lain. Ini sedikit seperti tata letak, cara yang sangat mirip bekerja di React Native. Namun, tidak ada kemungkinan akses langsung ke elemen. Untuk mengubah sesuatu di layar, Anda harus memperbarui seluruh layar, atau menggunakan pengontrol khusus yang ditambahkan sebelumnya ke widget selama pembuatannya.
- Antarmuka dibuat menggunakan kode, yang membuat garis antara logika dan desain jauh lebih tipis.
Di sisi lain, pendekatan ini memudahkan untuk membagi layar menjadi komponen yang terpisah. Bahkan, setiap blok elemen antarmuka yang tertanam dapat dipindahkan ke widget terpisah hanya dalam beberapa langkah, dan ini jauh lebih mudah daripada membuat tampilan dan fragmen kustom.
+ Antarmuka mudah dibagi menjadi modul terpisah
Dua komentar terakhir mungkin perlu diperiksa. Untuk melakukan ini, kami akan menulis aplikasi sederhana yang menunjukkan beberapa fitur Flutter. Ini akan menjadi aplikasi dengan bilah navigasi standar dan bilah tab.
Mari kita membuat tiga tab:
1) Pertama - dengan teks dan bilah geser untuk menyesuaikan ukuran dan warna teks
2) Tambahkan gambar yang dapat diunduh ke yang kedua (dengan indikator kemajuan)
3) Di tempat ketiga daftar contoh

Juga anggap kita awalnya tidak membagi antarmuka aplikasi menjadi tab terpisah. Di Flutter, Anda dapat menerapkan layar ini tanpa menggunakan fragmen. Tentu saja, partisi seperti itu masih diinginkan, tetapi anggaplah bahwa mereka lupa melakukannya, atau desain telah berubah, setelah itu pengembangan dilanjutkan oleh inersia oleh satu kelas.
Sekarang pertimbangkan kode sumber yang mengimplementasikan tata letak ini:
void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Home Page'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); }
Fragmen kode ini adalah standar untuk hampir semua aplikasi Flutter (dibuat bersama dengan proyek).
MyApp adalah kelas aplikasi itu sendiri, di mana, saat membuat MaterialApp, parameter umum dijelaskan: nama aplikasi, font, warna dan gaya. Layar utama aplikasi juga ditunjukkan di sini (bagi kami, ini adalah MyHomePage).
Mari kita buat catatan penting: di Flutter, widget dibagi menjadi dua jenis:
1) StatefulWidget
2) StatelessWidget
Diperlukan dua kelas untuk mendeskripsikan StatefulWidget: kelas widget itu sendiri dan kelas statusnya (di mana pekerjaan utama akan berlangsung).
StatelessWidget dijelaskan oleh satu kelas dengan kondisi tetap, dan itu hanya dapat diubah dengan membuat ulang dari widget utama. Karena itu, untuk keperluan kami, StatefulWidget diperlukan.
Sekarang pertimbangkan _MyHomePageState:
class _MyHomePageState extends State<MyHomePage> { int _currentIndex = 0; double _size = 14; double _r = 0; double _g = 0; double _b = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: <Widget>[
Untuk memudahkan persepsi, tab dengan teks ditandai dengan warna merah, tab dengan gambar berwarna hijau, tab daftar berwarna biru, dan menu navigasi berwarna kuning. Seperti yang Anda lihat, antarmuka digambarkan sebagai satu set widget (dan susunannya) yang tertanam satu sama lain:




Fungsi yang digunakan:
void _onTapped(int index) { setState(() { _currentIndex = index; }); } void _setTextStyle( {double size = -1, double r = -1, double g = -1, double b = -1}) { setState(() { if (size > 0) { _size = size; } if (r > 0) { _r = r; } if (g > 0) { _g = g; } if (b > 0) { _b = b; } }); } }
Mari kita pertimbangkan secara lebih rinci:
onTapped - fungsi yang dipanggil saat mengganti tab di menu bawah. Ini memanggil fungsi setState khusus, yang memungkinkan Anda untuk memperbarui widget saat ini dengan data baru (dan kami memperbarui variabel _currentIndex).
Mari kita lihat di mana itu berlaku:
body: <Widget>[ ][_currentIndex]
Di sini kita berurusan dengan sebuah array, dari mana menggunakan _currentIndex salah satu opsi tata letak layar dipilih, dan itu diganti sebagai salah satu tab.
Berikutnya adalah fungsi _setTextStyle. Ini memiliki iklan yang sangat tidak biasa untuk bahasa mirip C.
void _setTextStyle({double size = -1, double r = -1, double g = -1,double b = -1})
Argumen yang diteruskan bukan sebagai daftar, tetapi sebagai array. Ini adalah salah satu fitur yang sangat menarik dari Dart, yang memungkinkan Anda untuk membuat fungsi dengan sejumlah variabel argumen jauh lebih halus daripada apa yang terjadi di sebagian besar bahasa lain.
Karena setiap argumen diberi nama, kita dapat mengambilnya secara acak. Sebagai contoh:
_setTextStyle(size: 24, b: 255)
Mari kita pecahkan kelas layar lebar menjadi widget. Cara terbaik untuk dipecah oleh elemen logis, dalam kasus kami ini adalah tab. Berkat fitur Flutter, untuk ini cukup bagi kami untuk mengambil fragmen kode yang bertanggung jawab untuk setiap tab dan mentransfernya bersama-sama dengan logika untuk memisahkan kelas menggunakan metode build.
Tab pertama:
class TextWidget extends StatefulWidget { @override _TextWidgetState createState() => _TextWidgetState(); } class _TextWidgetState extends State<TextWidget> { double _size = 14; double _r = 0; double _g = 0; double _b = 0; @override Widget build(BuildContext context) { return Column( children: <Widget>[ Text("Example String", style: TextStyle( fontSize: _size, color: Color.fromRGBO(_r.toInt(), _g.toInt(), _b.toInt(), 1))), Container(constraints: BoxConstraints.expand(height: 32.0)), Slider( label: "${_size.toInt()} sp", value: _size, min: 10, max: 48, divisions: 38, activeColor: Colors.black, inactiveColor: Colors.grey, onChanged: (val) => _setTextStyle(size: val)), Slider( label: _r.toInt().toString(), value: _r, min: 0, max: 255, divisions: 255, activeColor: Colors.red, inactiveColor: Colors.grey, onChanged: (val) => _setTextStyle(r: val), ), Slider( label: _g.toInt().toString(), value: _g, min: 0, max: 255, divisions: 255, activeColor: Colors.green, inactiveColor: Colors.grey, onChanged: (val) => _setTextStyle(g: val), ), Slider( label: _b.toInt().toString(), value: _b, min: 0, max: 255, divisions: 256, activeColor: Colors.blue, inactiveColor: Colors.grey, onChanged: (val) => _setTextStyle(b: val), ), ], ); } }
Karena widget perlu diperbarui (metode _setTextStyle), kami menggunakan StatefulWidget.
Tidak perlu memperbarui untuk dua tab berikutnya, jadi kami akan menggunakan StatelessWidget.
Tab kedua:
class ImageWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Stack( children: <Widget>[ Center(child: CircularProgressIndicator()), Center( child: FadeInImage.memoryNetwork( placeholder: kTransparentImage, image: 'https://picsum.photos/250?image=9', ), ), ], ); } }
Tab ketiga:
class ListWidget extends StatelessWidget { @override Widget build(BuildContext context) { return ListView.builder( itemCount: 25, itemBuilder: (BuildContext context, int index) { return Container( child: Text( 'entry $index', style: TextStyle(color: Colors.white), ), margin: EdgeInsets.all(16.0), padding: EdgeInsets.all(16.0), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.all( Radius.circular(16.0), ), ), ); }, ); } }
Kode status layar utama berubah:
class _MyHomePageState extends State<MyHomePage> { int _currentIndex = 0; Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), actions: <Widget>[ IconButton(icon: Icon(Icons.navigate_next), onPressed: next) ], ), body: <Widget>[ TextWidget(), ImageWidget(), ListWidget(), ][_currentIndex], bottomNavigationBar: BottomNavigationBar( currentIndex: _currentIndex, onTap: _onTapped, items: [ BottomNavigationBarItem( icon: new Icon(Icons.text_format), title: new Text('Text'), ), BottomNavigationBarItem( icon: new Icon(Icons.image), title: new Text('Image'), ), BottomNavigationBarItem( icon: Icon(Icons.list), title: Text('ListView'), ) ], )); }
Jadi, kami dengan mudah membagi satu layar besar menjadi satu layar kecil dan tiga widget kecil. Anda dapat melihat bahwa pada layar Flutter secara konseptual tidak berbeda dengan widget (lebih tepatnya, widget menggunakan fungsi dari kedua aktivitas, fragmen, dan tampilan khusus). Fitur ini sangat nyaman ketika aplikasi membutuhkan tampilan layar penuh dari elemen apa pun - untuk ini Anda dapat menggunakan widget kami dengan penyempurnaan minimal.
Namun ada perbedaan minimal antara widget yang digunakan sebagai layar dan widget biasa. Elemen root untuk widget layar harus berupa objek Scaffold (memungkinkan Anda untuk menambahkan appBar, bottomNavigationBar, floatingActionButton, drawer, dll.).
Widget reguler tidak memiliki batasan ini, karena menggunakan metode build, mereka akan tertanam di layar utama, di mana Scaffold sudah tersedia.
Untungnya, menambahkan Scaffold ke widget reguler tidak memengaruhi kinerjanya.
Anda juga dapat menambahkan SafeArea (untuk memberikan indentasi untuk bilah status). Konversi sederhana berikut diperoleh:
Dari:
@override Widget build(BuildContext context) { return []; }
Kepada:
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: [] ), ); }
Nah, sekarang kembali ke pembahasan pro dan kontra Flutter.
Flutter baru-baru ini dirilis, jadi bug cukup umum. Ini terutama terlihat ketika memperbarui Flutter - beberapa perpustakaan mulai bekerja dengan kesalahan.
- Ketidakstabilan (baru saja meninggalkan beta)
Jelas, ketika menggunakan kerangka kerja baru, Anda memiliki perpustakaan jauh lebih sedikit yang Anda inginkan daripada dengan pengembangan Android / iOS asli. Namun, masih ada cukup banyak perpustakaan untuk Flutter, dan mereka terus muncul dengan kecepatan tinggi. Misalnya, banyak perpustakaan ditambahkan pada paruh kedua tahun 2018, tampaknya, dalam persiapan untuk rilis stabil pertama, dan perpustakaan paling penting (Google Analytics, Firebase, Maps, dll.) Ada sebelum itu.
- Perpustakaan kurang dari untuk pengembangan asli
+ Perpustakaan paling penting sudah ada di sana, yang baru terus keluar
Saatnya mengambil stok! Mari kita ingat semua pro dan kontra, mengatur elemen dari plus paling signifikan hingga minus paling signifikan:
+ Lintas-platform
+ Perspektif dan pengembangan aktif
+ Perpustakaan paling penting sudah ada di sana, yang baru terus keluar
+ Mesin grafis sendiri
+ Antarmuka mudah dibagi menjadi modul terpisah
- Paket instalasi akhir lebih besar, karena mesin virtual Dart ditambahkan ke dalamnya
- Antarmuka dibuat menggunakan kode, yang membuat garis antara logika dan desain jauh lebih tipis
- Lebih sedikit perpustakaan (dan informasi) daripada untuk pengembangan asli
- Ketidakstabilan (baru saja meninggalkan beta)
Terima kasih atas perhatian anda!