Anda di halaman 1dari 185

Machine Translated by Google

Saya
Machine Translated by Google

Tentang Tutorial
Flutter adalah framework open source untuk membuat aplikasi seluler berkualitas tinggi dan berperforma tinggi di
seluruh sistem operasi seluler - Android dan iOS. Ini menyediakan SDK yang sederhana, kuat, efisien, dan mudah
dipahami untuk menulis aplikasi seluler dalam bahasa Google sendiri, Dart.

Tutorial ini membahas dasar-dasar framework Flutter, pemasangan Flutter SDK, menyiapkan Android Studio untuk
mengembangkan aplikasi berbasis Flutter, arsitektur framework Flutter, dan mengembangkan semua jenis aplikasi
seluler menggunakan framework Flutter.

Hadirin
Tutorial ini disiapkan untuk para profesional yang bercita-cita untuk berkarier di bidang aplikasi seluler. Tutorial ini
dimaksudkan untuk membuat Anda nyaman dalam memulai framework Flutter dan berbagai fungsinya.

Prasyarat
Tutorial ini ditulis dengan asumsi bahwa pembaca sudah mengetahui apa itu Framework dan bahwa pembaca
memiliki pengetahuan yang baik tentang Pemrograman Berorientasi Objek dan pengetahuan dasar tentang
kerangka kerja Android dan pemrograman Dart.

Jika Anda seorang pemula dalam salah satu konsep ini, kami menyarankan Anda untuk membaca tutorial yang
terkait dengan ini terlebih dahulu, sebelum memulai dengan Flutter.

Hak Cipta & Penafian


@Hak Cipta 2019 oleh Tutorials Point (I) Pvt. Ltd.

Semua konten dan grafik yang diterbitkan dalam e-book ini adalah milik Tutorials Point (I)
Prajurit Ltd. Pengguna e-book ini dilarang untuk menggunakan kembali, mempertahankan, menyalin,
mendistribusikan atau menerbitkan kembali isi atau bagian dari isi e-book ini dengan cara apapun tanpa persetujuan
tertulis dari penerbit.

Kami berusaha untuk memperbarui konten situs web dan tutorial kami tepat waktu dan setepat mungkin, namun
kontennya mungkin mengandung ketidakakuratan atau kesalahan. Tutorial Point (I) Pvt.
Ltd. tidak memberikan jaminan mengenai keakuratan, ketepatan waktu, atau kelengkapan situs web
kami atau kontennya termasuk tutorial ini. Jika Anda menemukan kesalahan di situs web kami atau
dalam tutorial ini, beri tahu kami di contact@tutorialspoint.com

Saya
Machine Translated by Google

Berdebar

Daftar isi
Tentang Tutorial ............................................................... ............................................................... ...........................................Saya

Hadirin................................................. ............................................................... ............................................................... ......Saya

Prasyarat................................................... ............................................................... ............................................................... Saya

Hak Cipta & Penafian ............................................................... ............................................................... ....................................Saya

Daftar isi............................................... ............................................................... ..............................................ii

1. FLUTTER – PENDAHULUAN ............................................... ............................................................... ... 1

Fitur Flutter ............................................................... ............................................................... ..............................................1

Keuntungan Flutter .............................................................. ............................................................... ...................................................2

Kekurangan Flutter................................................... ............................................................... ..............................................2

2. FLUTTER – PEMASANGAN ............................................. ............................................................... ...... 3

Instalasi di Windows................................................... ............................................................... ..............................................3

Instalasi di MacOS................................................... ............................................................... ..............................................4

3. FLUTTER – MEMBUAT APLIKASI SEDERHANA DI ANDROID STUDIO ............................................... 5

4. FLUTTER – ARSITEKTUR APLIKASI FLUTTER ............................................... ............ 12

Widget .............................................................. ............................................................... ............................................................... ....12

Isyarat ............................................... ............................................................... ............................................................... ...13

Konsep Negara ............................................... ............................................................... ..............................................13

Lapisan ............................................................... ............................................................... ............................................................... .......13

5. FLUTTER – PENGENALAN PEMROGRAMAN DART ............................................... ............. 15

Variabel dan Tipe Data ............................................... ............................................................... ........................................15

Pengambilan Keputusan dan Putaran .............................................. ............................................................... ...........................16

Fungsi ............................................................... ............................................................... ............................................................... ..16

Pemrograman berorientasi objek............................................... ............................................................... ......................17

6. FLUTTER – PENGENALAN WIDGET ............................................... ........................................ 18

ii
Machine Translated by Google

Berdebar

Visualisasi Pembuatan Widget ............................................... ............................................................... ..............................19

7. FLUTTER – PENGENALAN TATA LETAK ............................................... ................................... 26

Jenis Widget Tata Letak .............................................. ............................................................... ..............................................26

Widget Anak Tunggal ............................................... ............................................................... ...................................................26

Beberapa Widget Anak .............................................................. ............................................................... ...................................30

Aplikasi Tata Letak Lanjut ............................................... ............................................................... ........................31

8. FLUTTER – PENGENALAN GERAKAN ............................................... .............................. 40

9. FLUTTER – MANAJEMEN NEGARA ............................................ .............................................. 45

Manajemen Negara Efemeral ............................................... ............................................................... .....................45

Status Aplikasi - scoped_model .............................................. ............................................................... .................57

Navigasi dan Perutean ............................................... ............................................................... ..............................68

10. FLUTTER – ANIMASI ............................................... ............................................................... .... 82

Perkenalan................................................. ............................................................... ..............................................82

Kelas Berbasis Animasi ...................................................... ............................................................... ..............................82

Alur kerja Animasi Flutter ............................................... ............................................................... .................83

Aplikasi Kerja ................................................ ............................................................... ...................................84

11. FLUTTER – MENULIS KODE KHUSUS ANDROID .............................................. .................... 93

12. FLUTTER – MENULIS KODE KHUSUS IOS .......................................... .............................. 100

13. FLUTTER – PENGENALAN PAKET ............................................... .......................... 103

Jenis Paket ............................................................... ............................................................... ..............................................103

Menggunakan Paket Dart .............................................. ............................................................... ....................................104

Kembangkan Paket Plugin Flutter................................................... ............................................................... .................104

14. FLUTTER – MENGAKSES REST API ............................................... .............................................. 114

Konsep dasar................................................ ............................................................... ..............................................114

Mengakses Product service API................................................... ............................................................... ......................115

aku aku aku


Machine Translated by Google

Berdebar

15. FLUTTER – KONSEP DATABASE .............................................. .............................................. 125

SQLite ............................................... ............................................................... ............................................................... .....125

Cloud Firestore ............................................... ............................................................... ..............................................133

16. FLUTTER – INTERNASIONALISASI ......................................... .............................. 138

Menggunakan Paket intl ............................................... ............................................................... ...............................................143

17. FLUTTER – PENGUJIAN ............................................... ............................................................... ........ 147

Jenis Pengujian ............................................................... ............................................................... ..............................................147

Pengujian Widget................................................... ............................................................... ..............................................147

Langkah Terlibat ............................................... ............................................................... ..............................................148

Contoh Kerja ............................................... ............................................................... ...............................................149

18. FLUTTER – PENERAPAN ............................................... ................................................... 151

Aplikasi Android................................................... ............................................................... ....................................151

Aplikasi iOS ............................................... ............................................................... ..............................................151

19. FLUTTER – ALAT PENGEMBANGAN ............................................... .................................... 153

Set Widget ............................................... ............................................................... ..............................................153

Pengembangan Flutter dengan Kode Visual Studio .............................................. ...................................................153

Dart DevTools................................... ............. .............................................. ............... ...........................153

Flutter SDK................................................... ............................................................... ...................................................155

20. FLUTTER – MENULIS APLIKASI LANJUTAN ............................................... ................ 157

21. FLUTTER – KESIMPULAN ............................................... ............................................................... 180

iv
Machine Translated by Google

1. Flutter – Pendahuluan

Secara umum, mengembangkan aplikasi seluler adalah tugas yang kompleks dan menantang. Ada banyak kerangka kerja
yang tersedia untuk mengembangkan aplikasi seluler. Android menyediakan kerangka kerja asli berdasarkan bahasa Java
dan iOS menyediakan kerangka kerja asli berdasarkan bahasa Objective-C / Shift.

Namun, untuk mengembangkan aplikasi yang mendukung kedua OS tersebut, kita perlu membuat kode dalam dua bahasa
berbeda menggunakan dua kerangka kerja berbeda. Untuk membantu mengatasi kerumitan ini, terdapat kerangka kerja
seluler yang mendukung kedua OS. Kerangka kerja ini berkisar dari kerangka kerja aplikasi seluler hybrid berbasis HTML
sederhana (yang menggunakan HTML untuk Antarmuka Pengguna dan JavaScript untuk logika aplikasi) hingga kerangka
kerja khusus bahasa kompleks (yang melakukan tugas berat untuk mengubah kode menjadi kode asli). Terlepas dari
kesederhanaan atau kerumitannya, kerangka kerja ini selalu memiliki banyak kelemahan, salah satu kelemahan utamanya
adalah kinerjanya yang lambat.

Dalam skenario ini, Flutter – kerangka kerja sederhana dan berperforma tinggi berdasarkan bahasa Dart, memberikan
kinerja tinggi dengan merender UI secara langsung di kanvas sistem operasi, bukan melalui kerangka kerja asli.

Flutter juga menawarkan banyak widget siap pakai (UI) untuk membuat aplikasi modern. Widget ini dioptimalkan untuk
lingkungan seluler dan mendesain aplikasi menggunakan widget semudah mendesain HTML.

Untuk lebih spesifik, aplikasi Flutter itu sendiri adalah sebuah widget. Widget Flutter juga mendukung animasi dan gerakan.
Logika aplikasi didasarkan pada pemrograman reaktif. Widget secara opsional dapat memiliki status. Dengan mengubah
status widget, Flutter akan secara otomatis (pemrograman reaktif) membandingkan status widget (lama dan baru) dan
merender widget hanya dengan perubahan yang diperlukan alih-alih merender ulang seluruh widget.

Kami akan membahas arsitektur lengkap di bab-bab mendatang.

Fitur Flutter
Framework Flutter menawarkan fitur berikut kepada developer:

• Kerangka modern dan reaktif.

• Menggunakan bahasa pemrograman Dart dan sangat mudah dipelajari.


• Perkembangan cepat.
• Antarmuka pengguna yang cantik dan lancar.

• Katalog widget besar.

• Menjalankan UI yang sama untuk berbagai platform.


• Aplikasi berkinerja tinggi.

1
Machine Translated by Google

Berdebar

Keuntungan Flutter
Flutter hadir dengan widget cantik dan dapat disesuaikan untuk kinerja tinggi dan aplikasi seluler yang luar
biasa. Itu memenuhi semua kebutuhan dan persyaratan khusus. Selain itu, Flutter menawarkan lebih banyak
keuntungan seperti yang disebutkan di bawah ini:
• Dart memiliki repositori paket perangkat lunak yang besar yang memungkinkan Anda memperluas
kemampuan aplikasi Anda.

• Pengembang hanya perlu menulis satu basis kode untuk kedua aplikasi (platform Android dan iOS). Flutter
mungkin akan diperluas ke platform lain juga di masa mendatang.

• Flutter membutuhkan pengujian yang lebih rendah. Karena basis kode tunggalnya, cukup jika kita menulis
pengujian otomatis sekali untuk kedua platform.

• Kesederhanaan Flutter menjadikannya kandidat yang bagus untuk pengembangan cepat. Kemampuan
kustomisasi dan ekstensibilitas membuatnya semakin bertenaga.

• Dengan Flutter, developer memiliki kontrol penuh atas widget dan tata letaknya.

• Flutter menawarkan alat pengembang yang hebat, dengan hot reload yang luar biasa.

Kerugian dari Flutter


Meskipun banyak kelebihannya, flutter memiliki kelemahan berikut di dalamnya:

• Karena dikodekan dalam bahasa Dart, pengembang perlu mempelajari bahasa baru (meskipun mudah
dipelajari).

• Framework modern mencoba memisahkan logika dan UI sebanyak mungkin, tetapi di Flutter, antarmuka
pengguna dan logika saling bercampur. Kita bisa mengatasinya dengan menggunakan smart coding dan
menggunakan modul tingkat tinggi untuk memisahkan user interface dan logika.

• Flutter adalah framework lain untuk membuat aplikasi seluler. Pengembang mengalami kesulitan dalam
memilih alat pengembangan yang tepat di segmen yang padat penduduk.

2
Machine Translated by Google

2. Flutter – Instalasi Berdebar

Bab ini akan memandu Anda melalui penginstalan Flutter di komputer lokal Anda secara mendetail.

Instalasi di Windows
Di bagian ini, mari kita lihat cara menginstal Flutter SDK dan persyaratannya di sistem windows.

Langkah 1: Buka URL, https://flutter.dev/docs/get-started/install/windows dan unduh Flutter SDK terbaru. Pada April 2019,
versinya adalah 1.2.1 dan filenya adalah flutter_windows_v1.2.1-stable.zip.

Langkah 2: Buka zip arsip zip di folder, misalnya C:\flutter\

Langkah 3: Perbarui jalur sistem untuk menyertakan direktori flutter bin.

Langkah 4: Flutter menyediakan alat, dokter flutter untuk memeriksa apakah semua persyaratan pengembangan flutter
telah terpenuhi.

dokter berdebar

Langkah 5: Menjalankan perintah di atas akan menganalisis sistem dan menampilkan laporannya seperti yang
ditunjukkan di bawah ini:

Ringkasan dokter (untuk melihat semua detail, jalankan flutter doctor -v): [ÿ] Flutter
(Channel stable, v1.2.1, di Microsoft Windows [Versi 10.0.17134.706], locale en-US) [ÿ] Android
toolchain - kembangkan untuk Perangkat Android (Android SDK versi 28.0.3) [ÿ] Android Studio
(versi 3.2) [ÿ] VS Code, edisi 64-bit (versi 1.29.1)

[!] Perangkat terhubung!


Tidak ada perangkat yang tersedia

! Dokter menemukan masalah dalam 1 kategori.

Laporan itu mengatakan bahwa semua alat pengembangan tersedia tetapi perangkat tidak terhubung.
Kami dapat memperbaikinya dengan menghubungkan perangkat android melalui USB atau memulai emulator
android.

Langkah 6: Instal SDK Android terbaru, jika dilaporkan oleh dokter bergetar

Langkah 7: Instal Android Studio terbaru, jika dilaporkan oleh dokter bergetar

Langkah 8: Mulai emulator android atau sambungkan perangkat android asli ke sistem.

Langkah 9: Instal plugin Flutter dan Dart untuk Android Studio. Ini menyediakan template startup untuk membuat aplikasi
Flutter baru, opsi untuk menjalankan dan men-debug aplikasi Flutter di studio Android itu sendiri, dll.,

3
Machine Translated by Google

Berdebar

• Buka Android Studio.


• Klik File > Pengaturan > Plugin.
• Pilih plugin Flutter dan klik Instal.
• Klik Ya saat diminta untuk menginstal plugin Dart.

• Mulai ulang studio Android.

Instalasi di MacOS
Untuk menginstal Flutter di MacOS, Anda harus mengikuti langkah-langkah berikut:

Langkah 1: Buka URL, https://flutter.dev/docs/get-started/install/macos dan unduh Flutter SDK terbaru.


Pada April 2019, versinya adalah 1.2.1 dan filenya adalah flutter_macos_v1.2.1- stable.zip.

Langkah 2: Buka zip arsip zip di folder, misalnya /path/to/flutter

Langkah 3: Perbarui jalur sistem untuk menyertakan direktori flutter bin (dalam file ~/.bashrc).

> ekspor PATH="$PATH:/path/ke/flutter/bin"

Langkah 4: Aktifkan jalur yang diperbarui di sesi saat ini menggunakan perintah di bawah ini dan kemudian
verifikasi juga.

sumber ~/.bashrc
sumber $HOME/.bash_profile
echo $PATH

Flutter menyediakan alat, dokter flutter untuk memeriksa apakah semua persyaratan pengembangan flutter
terpenuhi. Ini mirip dengan mitra Windows.

Langkah 5: Instal XCode terbaru, jika dilaporkan oleh dokter bergetar

Langkah 6: Instal SDK Android terbaru, jika dilaporkan oleh dokter bergetar

Langkah 7: Instal Android Studio terbaru, jika dilaporkan oleh dokter bergetar

Langkah 8: Mulai emulator android atau sambungkan perangkat android asli ke sistem untuk mengembangkan
aplikasi android.

Langkah 9: Buka simulator iOS atau sambungkan perangkat iPhone asli ke sistem untuk mengembangkan
aplikasi iOS.

Langkah 10: Instal plugin Flutter dan Dart untuk Android Studio. Ini menyediakan template startup untuk
membuat aplikasi Flutter baru, opsi untuk menjalankan dan men-debug aplikasi Flutter di studio Android itu
sendiri, dll.,

• Buka Android Studio.


• Klik Preferensi > Plugin.
• Pilih plugin Flutter dan klik Instal.
• Klik Ya saat diminta untuk menginstal plugin Dart.
• Mulai ulang studio Android.

4
Machine Translated by Google

3. Flutter – Membuat Aplikasi Sederhana Berdebar

di Android Studio

Pada bab ini, mari kita membuat aplikasi Flutter sederhana untuk memahami dasar-dasar pembuatan
aplikasi flutter di Android Studio.

Langkah 1: Buka Android Studio

Langkah 2: Buat Proyek Flutter. Untuk ini, klik File -> New -> New Flutter Project

5
Machine Translated by Google

Berdebar

Langkah 3: Pilih Aplikasi Flutter. Untuk ini, pilih Flutter Application dan klik Next.

Langkah 4: Konfigurasikan aplikasi seperti di bawah ini dan klik Berikutnya.

• Nama proyek: hello_app


• Jalur Flutter SDK: <path_to_flutter_sdk>
• Lokasi Proyek: <path_to_project_folder> • Deskripsi:
Aplikasi hello world berbasis Flutter

6
Machine Translated by Google

Berdebar

Langkah 5: Konfigurasi Proyek.

Tetapkan domain perusahaan sebagai flutterapp.tutorialspoint.com dan klik Selesai

Langkah 6: Masukkan domain Perusahaan.

Android Studio membuat aplikasi flutter yang berfungsi penuh dengan fungsionalitas minimal.
Mari kita periksa struktur aplikasi dan kemudian ubah kode untuk melakukan tugas kita.

7
Machine Translated by Google

Berdebar

Struktur aplikasi dan tujuannya adalah sebagai berikut:

Berbagai komponen struktur aplikasi dijelaskan di sini:

• android - Kode sumber yang dihasilkan secara otomatis untuk membuat aplikasi android
• ios - Kode sumber yang dihasilkan secara otomatis untuk membuat aplikasi ios

• lib - Folder utama yang berisi kode Dart yang ditulis menggunakan framework flutter

• lib/main.dart - Titik masuk aplikasi Flutter

• test - Folder yang berisi kode Dart untuk menguji aplikasi flutter

• test/widget_test.dart - Contoh kode

• .gitignore - File kontrol versi Git

• .metadata - dihasilkan secara otomatis oleh alat flutter

• .packages - dihasilkan secara otomatis untuk melacak paket flutter


• .iml - file proyek yang digunakan oleh Android studio

• pubspec.yaml - Digunakan oleh Pub, pengelola paket Flutter

• pubspec.lock - Otomatis dibuat oleh pengelola paket Flutter, Pub

• README.md - File deskripsi proyek ditulis dalam format Markdown

8
Machine Translated by Google

Berdebar

Langkah 7: Ganti kode dart di file lib/ main.dart dengan kode di bawah ini:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

kembalikan MaterialApp(
title: 'Hello World Demo Application', theme:
ThemeData( primarySwatch: Colors.blue, ), home:
MyHomePage(title: 'Home page'), );

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
Text( 'Hello World',

), );
}
}

Mari kita pahami kode dart baris demi baris.

• Baris 1: mengimpor paket flutter, material. Materinya adalah paket flutter untuk membuat
antarmuka pengguna sesuai dengan pedoman desain Material yang ditentukan oleh Android .

• Baris 3: Ini adalah titik masuk aplikasi Flutter. Memanggil fungsi runApp dan meneruskannya
sebagai objek kelas MyApp . Tujuan dari fungsi runApp adalah untuk melampirkan widget
yang diberikan ke layar.

• Baris 5 - 17: Widget digunakan untuk membuat UI dalam framework flutter. StatelessWidget
adalah widget, yang tidak mempertahankan status widget apa pun. MyApp memperluas
StatelessWidget dan mengganti metode pembuatannya . Tujuan dibangunnya

9
Machine Translated by Google

Berdebar

Metodenya adalah membuat bagian dari UI aplikasi. Di sini, metode build menggunakan
MaterialApp, sebuah widget untuk membuat UI level root dari aplikasi. Ini memiliki tiga
properti - judul, tema , dan rumah.

o title adalah judul aplikasi.

o tema adalah tema widget. Di sini, kami menetapkan warna biru sebagai warna
keseluruhan aplikasi menggunakan kelas ThemeData dan propertinya, primarySwatch.

o rumah adalah UI bagian dalam aplikasi, yang kami atur widget lain,
Halaman Beranda Saya

• Baris 19 - 38: MyHomePage sama dengan MyApp kecuali mengembalikan Widget


Scaffold . Scaffold adalah widget tingkat atas di sebelah widget MaterialApp yang
digunakan untuk membuat desain material yang sesuai dengan UI. Ini memiliki dua
properti penting, appBar untuk menampilkan tajuk aplikasi dan badan untuk menampilkan
konten aplikasi yang sebenarnya. AppBar adalah widget lain untuk merender header
aplikasi dan kami telah menggunakannya di properti appBar . Di properti tubuh , kami telah
menggunakan widget Pusat , yang memusatkannya pada widget anak. Teks adalah widget
paling akhir dan paling dalam untuk menampilkan teks dan ditampilkan di tengah
layar.

Langkah 8: Sekarang, jalankan aplikasi menggunakan, Run -> Run main.dart

10
Machine Translated by Google

Berdebar

Langkah 9: Akhirnya, output dari aplikasi adalah sebagai berikut:

11
Machine Translated by Google

4. Flutter – Arsitektur Aplikasi Flutter Berdebar

Dalam bab ini, mari kita bahas arsitektur framework Flutter.

Widget
Konsep inti framework Flutter adalah Di Flutter, Semuanya adalah widget. Widget pada dasarnya
adalah komponen antarmuka pengguna yang digunakan untuk membuat antarmuka pengguna aplikasi.

Di Flutter, aplikasi itu sendiri adalah sebuah widget. Aplikasi ini adalah widget tingkat atas dan UI-nya
dibangun menggunakan satu atau lebih turunan (widget), yang dibangun lagi menggunakan widget
turunannya. Fitur komposisi ini membantu kami membuat antarmuka pengguna dengan kerumitan apa pun.

Misalnya, hirarki widget dari aplikasi hello world (dibuat di bab sebelumnya) seperti yang ditentukan
dalam diagram berikut:

Di sini poin-poin berikut patut diperhatikan:

12
Machine Translated by Google

Berdebar

• MyApp adalah widget yang dibuat pengguna dan dibuat menggunakan widget asli Flutter,
Aplikasi Bahan.

• MaterialApp memiliki properti rumah untuk menentukan antarmuka pengguna halaman beranda,
yang lagi-lagi merupakan widget buatan pengguna, MyHomePage.

• MyHomePage dibangun menggunakan widget native flutter lainnya, Scaffold.

• Scaffold memiliki dua properti – body dan appBar.

• body digunakan untuk menentukan antarmuka pengguna utamanya dan appBar digunakan untuk menentukan headernya
antarmuka pengguna.

• Header UI dibuat menggunakan widget asli flutter, AppBar dan Body UI dibuat menggunakan
Widget tengah .

• Widget Tengah memiliki properti, Anak, yang mengacu pada konten aktual dan dibangun menggunakan widget Teks .

Gerakan

Widget Flutter mendukung interaksi melalui widget khusus, GestureDetector.


GestureDetector adalah widget tak terlihat yang memiliki kemampuan untuk menangkap interaksi pengguna seperti
mengetuk, menyeret, dll., dari widget turunannya. Banyak widget asli Flutter mendukung interaksi melalui penggunaan
GestureDetector. Kita juga dapat memasukkan fitur interaktif ke dalam widget yang ada dengan menyusunnya menggunakan
widget GestureDetector . Kami akan mempelajari gerakan secara terpisah di bab-bab mendatang.

Konsep Negara
Widget Flutter mendukung pemeliharaan State dengan menyediakan widget khusus, StatefulWidget.
Widget harus diturunkan dari widget StatefulWidget untuk mendukung pemeliharaan status dan semua widget lainnya
harus diturunkan dari StatelessWidget. Widget Flutter bersifat reaktif secara native. Ini mirip dengan reactjs dan
StatefulWidget akan dirender secara otomatis setiap kali keadaan internalnya diubah. Perenderan ulang dioptimalkan
dengan menemukan perbedaan antara UI widget lama dan baru dan hanya merender perubahan yang diperlukan.

Lapisan
Konsep paling penting dari framework Flutter adalah bahwa framework dikelompokkan ke dalam beberapa kategori dalam
hal kompleksitas dan disusun dengan jelas dalam lapisan-lapisan dengan kompleksitas yang menurun. Lapisan dibangun
menggunakan lapisan tingkat berikutnya langsung. Lapisan paling atas adalah widget khusus untuk Android dan iOS.
Lapisan berikutnya memiliki semua widget asli bergetar. Lapisan berikutnya adalah lapisan Rendering , yang merupakan
komponen perender tingkat rendah dan merender semua yang ada di aplikasi flutter. Lapisan turun ke kode khusus
platform inti.

13
Machine Translated by Google

Berdebar

Gambaran umum layer di Flutter ditentukan dalam diagram di bawah ini:

Poin-poin berikut meringkas arsitektur Flutter:


• Di Flutter, semuanya adalah widget dan widget kompleks terdiri dari widget yang sudah ada.

• Fitur interaktif dapat digabungkan kapan pun diperlukan menggunakan widget GestureDetector .

• Status widget dapat dipertahankan kapan pun diperlukan menggunakan StatefulWidget


widget.

• Flutter menawarkan desain berlapis sehingga setiap lapisan dapat diprogram tergantung pada
kerumitan tugas.

Kami akan membahas semua konsep ini secara rinci di bab-bab mendatang.

14
Machine Translated by Google

5. Flutter – Pengantar Pemrograman Dart Berdebar

Dart adalah bahasa pemrograman tujuan umum sumber terbuka. Ini awalnya dikembangkan oleh
Google. Dart adalah bahasa berorientasi objek dengan sintaks C-style. Ini mendukung konsep
pemrograman seperti antarmuka, kelas, tidak seperti bahasa pemrograman lain Dart tidak mendukung
array. Koleksi Dart dapat digunakan untuk mereplikasi struktur data seperti array, generik, dan
pengetikan opsional.

Kode berikut menunjukkan program Dart sederhana:

batal main() {

print("Bahasa Dart mudah dipelajari");


}

Variabel dan tipe Data


Variabel diberi nama lokasi penyimpanan dan tipe Data hanya mengacu pada jenis dan ukuran data
yang terkait dengan variabel dan fungsi.

Dart menggunakan kata kunci var untuk mendeklarasikan variabel. Sintaks var didefinisikan di bawah ini,

var name = 'Panah';

Kata kunci final dan const digunakan untuk mendeklarasikan konstanta. Mereka didefinisikan sebagai berikut:

batal main()
{ final a = 12;
const pi = 3,14;
cetak(a); cetak(pi);

Bahasa Dart mendukung tipe data berikut:

• Bilangan: Digunakan untuk mewakili literal numerik – Integer dan Double.

• String: Ini mewakili urutan karakter. Nilai string ditentukan dalam tanda kutip tunggal atau ganda.

• Boolean: Dart menggunakan kata kunci bool untuk mewakili nilai Boolean – benar dan salah.

• Daftar dan Peta: Ini digunakan untuk mewakili kumpulan objek. Daftar sederhana dapat
didefinisikan sebagai berikut:

batal main()
{ var daftar = [1,2,3,4,5];
cetak(daftar);
}

15
Machine Translated by Google

Berdebar

Daftar yang ditunjukkan di atas menghasilkan daftar [1,2,3,4,5].

Peta dapat didefinisikan seperti yang ditunjukkan di sini:

void main() { var


mapping = {'id': 1,'name':'Dart'}; cetak(pemetaan);

• Dinamis: Jika tipe variabel tidak ditentukan, maka tipe defaultnya adalah dinamis. Itu
contoh berikut mengilustrasikan variabel tipe dinamis:

void main()
{ nama dinamis = "Dart";
cetak(nama);
}

Pengambilan Keputusan dan Loops


Blok pengambilan keputusan mengevaluasi kondisi sebelum instruksi dieksekusi. Dart mendukung
pernyataan If, If..else dan switch.

Loop digunakan untuk mengulang blok kode sampai kondisi tertentu terpenuhi. Dart mendukung untuk,
untuk..di , while dan do.. while loop.

Mari kita pahami contoh sederhana tentang penggunaan pernyataan kontrol dan loop:

void main()
{ for( var i = 1 ; i <= 10; i++ ) { if(i%2==0) {

cetak(i);
}
}
}

Kode di atas mencetak angka genap dari 1 sampai 10.

Fungsi
Fungsi adalah sekelompok pernyataan yang bersama-sama melakukan tugas tertentu. Mari kita lihat fungsi
sederhana di Dart seperti yang ditunjukkan di sini:

batal main()
{ tambah(3,4);
}

batal tambahkan(int a,int b)


{ int c; c=a+b; cetak(c);

16
Machine Translated by Google

Berdebar

Fungsi di atas menambahkan dua nilai dan menghasilkan 7 sebagai output.

Pemrograman berorientasi objek


Dart adalah bahasa berorientasi objek. Ini mendukung fitur pemrograman berorientasi objek seperti kelas, antarmuka, dll.

Kelas adalah cetak biru untuk membuat objek. Definisi kelas mencakup hal-hal berikut:

• Bidang

• Getter dan setter

• Konstruktor

• Fungsi

Sekarang, mari kita buat kelas sederhana menggunakan definisi di atas:

kelas Karyawan {
nama string;

// metode pengambil
String dapatkan emp_name
{ nama kembali;
}

//metode penyetel void


set emp_name(String name) { this.name = nama;

// definisi fungsi membatalkan


hasil () {

cetak(nama);
}

} void main() { //
pembuatan objek
Karyawan emp = Karyawan baru();
emp.name="karyawan1"; emp.hasil(); //
pemanggilan fungsi
}

17
Machine Translated by Google

6. Flutter – Pengantar Widget Berdebar

Seperti yang kita pelajari di bab sebelumnya, widget adalah segalanya dalam framework Flutter. Kami telah
mempelajari cara membuat widget baru di bab sebelumnya.

Di bab ini, mari kita pahami konsep sebenarnya di balik pembuatan widget dan berbagai jenis widget yang
tersedia di framework Flutter .

Mari kita periksa widget MyHomePage aplikasi Hello World . Kode untuk tujuan ini adalah seperti yang
diberikan di bawah ini:

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@mengesampingkan

Pembuatan widget(konteks BuildContext)


{ return Scaffold(
appBar:
AppBar( title: Text(this.title), ),
body: Center( child: Text( 'Hello
World', )),

);
}
}

Di sini, kami telah membuat widget baru dengan memperluas StatelessWidget.

Perhatikan bahwa StatelessWidget hanya membutuhkan satu metode build untuk diterapkan di kelas
turunannya. Metode build mendapatkan lingkungan konteks yang diperlukan untuk membuat widget melalui
parameter BuildContext dan mengembalikan widget yang dibuatnya.

Dalam kode, kami telah menggunakan title sebagai salah satu argumen konstruktor dan juga menggunakan
Key sebagai argumen lainnya. Judul digunakan untuk menampilkan judul dan Kunci digunakan untuk
mengidentifikasi widget di lingkungan build .

Di sini, metode build memanggil metode build Scaffold, yang selanjutnya memanggil metode build AppBar
dan Center untuk membangun antarmuka penggunanya.

Terakhir, metode pembuatan Pusat memanggil metode pembuatan Teks .

18
Machine Translated by Google

Berdebar

Untuk pemahaman yang lebih baik, representasi visual yang sama diberikan di bawah ini:

Visualisasi Pembuatan Widget


Di Flutter, widget dapat dikelompokkan ke dalam beberapa kategori berdasarkan fiturnya, seperti yang tercantum di bawah
ini:

• Widget khusus platform • Widget tata

letak • Widget pemeliharaan status

• Platform independen / widget dasar

Mari kita bahas masing-masing secara rinci sekarang.

Widget khusus platform


Flutter memiliki widget khusus untuk platform tertentu - Android atau iOS.

Widget khusus Android dirancang sesuai dengan panduan desain Material oleh OS Android. Widget khusus Android disebut
sebagai widget Material.

Widget khusus iOS dirancang sesuai dengan Pedoman Antarmuka Manusia oleh Apple dan disebut sebagai widget
Cupertino .

Beberapa widget material yang paling banyak digunakan adalah sebagai berikut:

• Perancah

AppBar

19
Machine Translated by Google

Berdebar

• Bilah Navigasi Bawah


• TabBar

• TabBarView

• ListTile

• Tombol Angkat

• Tombol Aksi Mengambang


• Tombol Datar

• Tombol Ikon

• Tombol Turun

• Tombol PopupMenu
• Bar Tombol

• Bidang Teks

• Kotak centang

• Radio

• Beralih

• Penggeser

• Pemilih Tanggal & Waktu

• SimpleDialog •

AlertDialog

Beberapa widget Cupertino yang paling banyak digunakan adalah sebagai berikut:

• Tombol Cupertino

• Cupertino Picker

• CupertinoDatePicker •

CupertinoTimerPicker

• CupertinoNavigationBar

• CupertinoTabBar

• CupertinoTabScaffold •

CupertinoTabView •

CupertinoTextField

• Dialog Cupertino

• Tindakan Dialog Cupertino

• CupertinoFullscreenDialogTransition •

CupertinoPageScaffold

• CupertinoPageTransition

• Lembar Tindakan Cupertino

• CupertinoActivityIndicator •

CupertinoAlertDialog •

CupertinoPopupSurface

20
Machine Translated by Google

Berdebar

• Cupertino Slider

Widget tata letak


Di Flutter, widget dapat dibuat dengan membuat satu atau beberapa widget. Untuk menyusun beberapa widget
menjadi satu widget, Flutter menyediakan sejumlah besar widget dengan fitur tata letak. Misalnya, widget anak
dapat dipusatkan menggunakan widget Tengah .

Beberapa widget tata letak yang populer adalah sebagai berikut:

• Kontainer: Kotak persegi panjang yang dihias menggunakan widget BoxDecoration dengan
latar belakang, batas dan bayangan.

• Center: Tengahkan widget anaknya

• Baris: Atur anak-anaknya dalam arah horizontal.

• Kolom: Atur anak-anaknya dalam arah vertikal.

• Stack: Susun satu di atas yang lain.

Kami akan memeriksa tata letak widget secara mendetail di bab Pengenalan widget tata letak yang akan datang .

Widget pemeliharaan negara


Di Flutter, semua widget berasal dari StatelessWidget atau StatefulWidget.

Widget yang diturunkan dari StatelessWidget tidak memiliki informasi status apa pun tetapi mungkin berisi widget
yang diturunkan dari StatefulWidget. Sifat dinamis dari aplikasi adalah melalui perilaku interaktif widget dan
perubahan status selama interaksi. Misalnya, mengetuk tombol penghitung akan menambah/mengurangi status
internal penghitung sebanyak satu dan sifat reaktif widget Flutter akan merender ulang widget secara otomatis
menggunakan informasi status baru.

Kita akan mempelajari konsep widget StatefulWidget secara mendetail di bab manajemen Status yang akan
datang .

Widget independen / dasar platform Flutter menyediakan

sejumlah besar widget dasar untuk membuat antarmuka pengguna yang sederhana dan kompleks dengan cara
independen platform. Mari kita lihat beberapa widget dasar di bab ini.

Teks

Widget teks digunakan untuk menampilkan seutas string. Gaya string dapat diatur dengan menggunakan properti
gaya dan kelas TextStyle . Contoh kode untuk tujuan ini adalah sebagai berikut:

Text('Halo Dunia!', gaya: TextStyle(fontWeight: FontWeight.bold))

Widget teks memiliki konstruktor khusus, Text.rich, yang menerima turunan dari tipe TextSpan untuk menentukan
string dengan gaya yang berbeda. Widget TextSpan bersifat rekursif dan menerima TextSpan sebagai turunannya.
Contoh kode untuk tujuan ini adalah sebagai berikut:

21
Machine Translated by Google

Berdebar

Text.rich( TextSpan( anak:


<TextSpan>[ TextSpan(teks: "Halo ", gaya: TextStyle(fontStyle:
FontStyle.italic)),
TextSpan(teks: "Dunia", gaya: TextStyle(fontWeight: FontWeight.bold)), ], ),

Properti paling penting dari widget Teks adalah sebagai berikut:

• maxLines, int: Jumlah maksimum baris yang akan ditampilkan

• luapan, TextOverFlow: Menentukan bagaimana limpahan visual ditangani menggunakan


kelas TextOverFlow

• style, TextStyle: Tentukan gaya string menggunakan kelas TextStyle

• textAlign, TextAlign: Perataan teks seperti kanan, kiri, ratakan, dll, menggunakan
kelas TextAlign

• textDirection, TextDirection: Arah teks mengalir, baik dari kiri ke kanan atau kanan
ke kiri

Gambar

Widget gambar digunakan untuk menampilkan gambar dalam aplikasi. Widget gambar menyediakan berbagai
konstruktor untuk memuat gambar dari berbagai sumber dan mereka adalah sebagai berikut:

• Gambar - Pemuat gambar umum menggunakan ImageProvider

• Image.asset - Memuat gambar dari aset proyek flutter

• Image.file - Memuat image dari folder sistem •

Image.memory - Memuat image dari memori • Image.Network

- Memuat image dari jaringan

Opsi termudah untuk memuat dan menampilkan gambar di Flutter adalah dengan menyertakan gambar sebagai
aset aplikasi dan memuatnya ke dalam widget sesuai permintaan.

• Buat folder, aset di folder proyek dan tempatkan gambar yang diperlukan.

• Tentukan aset di pubspec.yaml seperti yang ditunjukkan di bawah ini:

berdebar:
aktiva:
- aset/smiley.png

• Sekarang, muat dan tampilkan gambar di aplikasi.

Gambar.aset('aset/smiley.png')

22
Machine Translated by Google

Berdebar

• Kode sumber lengkap widget MyHomePage dari aplikasi hello world dan
hasilnya seperti gambar di bawah ini:

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title: Text(this.title), ),
body: Center( child: Image.asset("assets/
smiley.png")

), );
}

Gambar yang dimuat adalah seperti yang ditunjukkan di bawah ini:

23
Machine Translated by Google

Berdebar

Properti paling penting dari widget Gambar adalah sebagai berikut:

• image, ImageProvider: Gambar aktual yang akan dimuat


• width, double - Lebar gambar
• tinggi, ganda - Tinggi gambar
• keselarasan, AlignmentGeometry - Cara menyelaraskan gambar dalam batas-batasnya

Ikon

Widget ikon digunakan untuk menampilkan mesin terbang dari font yang dijelaskan di kelas IconData . Kode untuk
memuat ikon email sederhana adalah sebagai berikut:

Ikon(Ikon.email)

Adapun source code lengkap untuk mengaplikasikannya pada aplikasi hello world adalah sebagai berikut:

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
Icon(Icons.email)

), );
}
}

24
Machine Translated by Google

Berdebar

Ikon yang dimuat adalah seperti yang ditunjukkan di bawah ini:

25
Machine Translated by Google

7. Flutter – Pengantar Tata Letak Berdebar

Karena konsep inti Flutter adalah Semuanya adalah widget, Flutter menggabungkan fungsionalitas tata letak
antarmuka pengguna ke dalam widget itu sendiri. Flutter menyediakan cukup banyak widget yang didesain
khusus seperti Container, Center, Align, dll., hanya untuk tujuan tata letak antarmuka pengguna. Widget
yang dibuat dengan menyusun widget lain biasanya menggunakan widget tata letak. Mari kita pelajari konsep
tata letak Flutter di bab ini.

Jenis LayoutWidget
Widget tata letak dapat dikelompokkan menjadi dua kategori berbeda berdasarkan anaknya:

• Widget mendukung satu anak


• Widget mendukung banyak anak

Mari kita pelajari kedua jenis widget dan fungsinya di bagian yang akan datang.

Widget Anak Tunggal


Dalam kategori ini, widget hanya akan memiliki satu widget sebagai turunannya dan setiap widget akan
memiliki fungsi tata letak khusus.

Misalnya, widget Tengah hanya memusatkan widget anak-anak sehubungan dengan widget induknya dan
widget Kontainer memberikan fleksibilitas penuh untuk menempatkannya di tempat tertentu di dalamnya
menggunakan opsi berbeda seperti padding, dekorasi, dll.,

Widget anak tunggal adalah opsi bagus untuk membuat widget berkualitas tinggi yang memiliki fungsi tunggal
seperti tombol, label, dll.,

Kode untuk membuat tombol sederhana menggunakan widget Container adalah sebagai berikut:

kelas MyButton extends StatelessWidget {


MyButton({Key key}) : super(key: key);

@ganti
Widget build(BuildContext context) { return
Container( decoration: const
BoxDecoration( border: Border( top:
BorderSide(width: 1.0, color:
Color(0xFFFFFFFFFF)), kiri: BorderSide(width: 1.0, color:
Color(0xFFFFFFFFFF) )), kanan: BorderSide(width: 1.0, color:
Color(0xFFFF000000)), bawah: BorderSide(width: 1.0, color:
Color(0xFFFF000000)), ), ), child: Container(

bantalan: const EdgeInsets.simetris(horizontal: 20.0, vertikal: 2.0), dekorasi: const


BoxDecoration( perbatasan: Perbatasan( atas: Sisi Perbatasan(lebar: 1.0, warna:
Warna(0xFFFFDFDFDF)),

26
Machine Translated by Google

Berdebar

kiri: Sisi Tepi(lebar: 1,0, warna: Warna(0xFFFFDFDFDF)), kanan: Sisi


Tepi(lebar: 1,0, warna: Warna(0xFFFF7F7F7F)), bawah: Sisi Tepi(lebar: 1,0,
warna: Warna(0xFFFF7F7F7F)), ), warna: Warna.abu-abu, ), anak: const
Teks('OK', textAlign: TextAlign.center, gaya: TextStyle(warna:

Warna.hitam)), ), );

}
}

Di sini, kami telah menggunakan dua widget – widget Wadah dan widget Teks . Hasil dari widget adalah
sebagai tombol kustom seperti yang ditunjukkan di bawah ini:

Mari kita periksa beberapa widget tata letak anak tunggal terpenting yang disediakan oleh Flutter:

• Padding: Digunakan untuk mengatur widget turunannya dengan padding yang diberikan. Di sini, padding
dapat disediakan oleh kelas EdgeInsets .

• Align: Sejajarkan widget turunannya dengan sendirinya menggunakan nilai properti perataan . Nilai untuk
properti penyelarasan dapat diberikan oleh kelas FractionalOffset . Kelas FractionalOffset menentukan
offset dalam hal jarak dari kiri atas.

Beberapa kemungkinan nilai offset adalah sebagai berikut:

• FractionalOffset(1.0, 0.0) mewakili kanan atas.


• FractionalOffset(0.0, 1.0) mewakili kiri bawah.

• Contoh kode tentang offset ditunjukkan di bawah ini:

Tengah( anak:
Kontainer( tinggi:
100.0, lebar: 100.0,
warna: Warna.kuning,
anak: Ratakan( penjajaran:
FractionalOffset(0.2, 0.6), anak: Kontainer( tinggi:
40.0, lebar: 40.0, warna: Warna.merah , ), ), ), ),

• FittedBox: Menskalakan widget anak dan kemudian memposisikannya sesuai dengan kecocokan yang
ditentukan.

• AspectRatio: Ini mencoba mengubah ukuran widget anak ke rasio aspek yang ditentukan

27
Machine Translated by Google

Berdebar

• ConstrainedBox

• Garis dasar

• Kotak Berukuran Fraktinal

• Tinggi Intrinsik

• Lebar Intrinsik

• GluedBox

• Di Luar Panggung

• OverflowBox

• Ukuran Kotak

• SizedOverflowBox

• Transformasi

• CustomSingleChildLayout

Aplikasi hello world kami menggunakan widget tata letak berbasis bahan untuk mendesain halaman beranda. Mari
kita modifikasi aplikasi hello world kita untuk membangun halaman beranda menggunakan widget tata letak dasar
seperti yang ditentukan di bawah ini:

• Kontainer: Generik, anak tunggal, widget kontainer berbasis kotak dengan perataan, padding, batas, dan
margin bersama dengan fitur gaya yang kaya.

• Tengah: Sederhana, widget penampung anak tunggal, yang memusatkan widget anaknya.

Kode yang dimodifikasi dari widget MyHomePage dan MyApp adalah sebagai berikut:

kelas MyApp memperluas StatelessWidget {

@mengesampingkan

Pembuatan widget (konteks BuildContext) {

return MyHomePage(judul: "Aplikasi demo Hello World");

kelas MyHomePage memperluas StatelessWidget {

MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@mengesampingkan

Pembuatan widget (konteks BuildContext) {

kembalikan Wadah(

dekorasi: KotakDekorasi(

28
Machine Translated by Google

Berdebar

warna: Warna.putih,

),

padding: EdgeInsets.all(25),

anak: Tengah(anak:

Teks(
'Halo Dunia',

gaya: Gaya Teks(


warna: Warna.hitam,

jarak huruf: 0,5,


ukuran font: 20,

),
textDirection: TextDirection.ltr,

),

));
}

Di Sini,

• Widget wadah adalah widget tingkat atas atau root. Kontainer dikonfigurasi menggunakan properti dekorasi
dan padding untuk mengatur tata letak kontennya.

• BoxDecoration memiliki banyak properti seperti color, border, dll., untuk menghias widget Container dan
disini, color digunakan untuk mengatur warna container.

• padding widget Container diatur dengan menggunakan kelas dgeInsets , yang menyediakan opsi untuk
menentukan nilai padding.

• Center adalah widget turunan dari widget Container . Sekali lagi, Teks adalah turunan dari widget Tengah .
Teks digunakan untuk menampilkan pesan dan Pusat digunakan untuk memusatkan pesan teks
sehubungan dengan widget induk, Wadah.

29
Machine Translated by Google

Berdebar

Hasil akhir dari kode yang diberikan di atas adalah contoh tata letak seperti yang ditunjukkan di bawah ini:

Beberapa Widget Anak


Dalam kategori ini, widget tertentu akan memiliki lebih dari satu widget anak dan tata letak setiap widget unik.

Misalnya, widget Baris memungkinkan peletakan turunannya dalam arah horizontal, sedangkan widget Kolom memungkinkan
peletakan turunannya dalam arah vertikal. Dengan menyusun Baris dan Kolom, widget dengan tingkat kerumitan apa pun dapat
dibangun.

Mari kita pelajari beberapa widget yang sering digunakan di bagian ini.

• Baris - Memungkinkan untuk mengatur anak-anaknya secara horizontal.

• Kolom - Memungkinkan untuk mengatur anak-anaknya secara vertikal.

• ListView - Memungkinkan untuk mengatur anak-anaknya sebagai daftar.

• GridView - Memungkinkan untuk mengatur anak-anaknya sebagai galeri.

• Diperluas - Digunakan untuk membuat anak-anak dari widget Baris dan Kolom untuk menempati
luas maksimum yang memungkinkan.

30
Machine Translated by Google

Berdebar

• Tabel - Widget berbasis tabel.

• Aliran - Widget berbasis aliran.

• Tumpukan - Widget berbasis tumpukan.

Aplikasi Tata Letak Tingkat Lanjut


Di bagian ini, mari kita pelajari cara membuat antarmuka pengguna yang kompleks dari daftar produk dengan
desain khusus menggunakan widget tata letak anak tunggal dan ganda.

Untuk tujuan ini, ikuti urutan yang diberikan di bawah ini:

• Buat aplikasi Flutter baru di studio Android, product_layout_app.

• Ganti kode main.dart dengan kode berikut:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product layout
demo home page'), );

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@mengesampingkan

Pembuatan widget(konteks BuildContext)


{ return Scaffold(
appBar:
AppBar( judul: Teks(ini.judul), ),
badan: Pusat( anak:

Teks(
'Halo Dunia', )),

);
}
}

31
Machine Translated by Google

Berdebar

• Di Sini,

• Kami telah membuat widget MyHomePage dengan memperluas StatelessWidget alih-alih StatefulWidget default
dan kemudian menghapus kode yang relevan.

• Sekarang, buat widget baru, ProductBox sesuai dengan desain yang ditentukan seperti yang ditunjukkan
di bawah:

• Kode untuk ProductBox adalah sebagai berikut:

class ProductBox extends StatelessWidget { ProductBox({Key


key, this.name, this.description, this.price, this.image})
: super(kunci: kunci);

nama String akhir;


deskripsi String akhir; harga int akhir;
gambar String akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2), tinggi: 120,
anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak:


<Widget>[ Image.asset("assets/appimages/" + gambar), Diperluas( anak:
Kontainer( padding: EdgeInsets.all(5), anak: Kolom( mainAxisAlignment:
MainAxisAlignment.spaceEvenly , anak-anak: <Widget>[ Text(ini.nama,
gaya: TextStyle(fontWeight: FontWeight.bold)),

Teks(ini.deskripsi), Teks("Harga:
" + ini.harga.toString()), ], )))

]))); }
}

32
Machine Translated by Google

Berdebar

• Harap perhatikan kode berikut:

• ProductBox telah menggunakan empat argumen seperti yang ditentukan di bawah ini:

o nama - Nama produk

o deskripsi - Deskripsi produk

o harga - Harga produk

o gambar - Gambar produk

• ProductBox menggunakan tujuh widget bawaan seperti yang ditentukan di bawah ini:

o Kontainer

o Diperluas

o Baris

o Kolom

o Kartu

o Teks

o Gambar

33
Machine Translated by Google

Berdebar

• ProductBox dirancang menggunakan widget yang disebutkan di atas. Susunan atau hierarki widget
ditentukan dalam diagram yang ditunjukkan di bawah ini:

• Sekarang, tempatkan beberapa gambar tiruan (lihat di bawah) untuk informasi produk di folder aset aplikasi
dan konfigurasikan folder aset di file pubspec.yaml seperti yang ditunjukkan di bawah ini:

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/
pendrive.png - aset/appimages/pixel.png -
aset/appimages/tablet.png

iPhone.png

34
Machine Translated by Google

Berdebar

Piksel.png

Laptop.png

Tablet.png

Flashdisk.png

Floppy.png
• Terakhir, Gunakan widget ProductBox di widget MyHomePage seperti yang ditentukan di bawah ini:

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@mengesampingkan

Bangun widget (konteks BuildContext)


{ kembalikan Scaffold (appBar: AppBar
(judul: Teks ("Daftar Produk")), badan: ListView ( shrinkWrap:
true,

35
Machine Translated by Google

Berdebar

padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), anak-anak:


<Widget>[ ProductBox( name: "iPhone", deskripsi: "iPhone adalah ponsel
stylist yang pernah ada", harga: 1000, gambar: "iphone. png"),

ProductBox( nama:
"Pixel", deskripsi: "Pixel adalah ponsel paling berfitur yang pernah ada",
harga: 800, gambar: "pixel.png"), ProductBox( nama: "Laptop", deskripsi:
"Laptop adalah alat pengembangan paling produktif ", harga: 2000, gambar:
"laptop.png"),

ProductBox( nama:
"Tablet", deskripsi: "Tablet adalah perangkat paling berguna yang pernah ada
pertemuan",
harga: 1500,
gambar: "tablet.png"),

ProductBox( nama:
"Flashdisk", deskripsi: "Flashdisk adalah media penyimpanan yang
berguna", harga: 100, gambar: "flashdisk.png"), ProductBox(

nama: "Floppy Drive",


deskripsi: "Floppy drive adalah media penyimpanan penyelamat yang berguna",
harga: 20, gambar: "floppy.png"),

], ));
}
}

• Di sini, kami telah menggunakan ProductBox sebagai anak widget ListView .

• Kode lengkap (main.dart) dari aplikasi tata letak produk


(product_layout_app) adalah sebagai berikut:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget build(Konteks
BuildContext) {

kembalikan
MaterialApp( judul: 'Flutter
Demo', tema:
ThemeData( primarySwatch: Warna.biru,

36
Machine Translated by Google

Berdebar

),
beranda: MyHomePage(judul: 'Halaman beranda demo tata letak produk'), );

}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Listing")), body: ListView( shrinkWrap: true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , anak-anak:
<Widget>[ ProductBox( nama: "iPhone", deskripsi: "iPhone
adalah ponsel stylist yang pernah ada", harga: 1000, gambar: "iphone.png"),

ProductBox( nama:
"Pixel", deskripsi: "Pixel adalah ponsel paling berfitur yang pernah ada",
harga: 800, gambar: "pixel.png"), ProductBox( nama: "Laptop", deskripsi:
"Laptop adalah alat pengembangan paling produktif ", harga: 2000,
gambar: "laptop.png"),

ProductBox( nama:
"Tablet", deskripsi: "Tablet adalah perangkat paling berguna yang pernah ada
pertemuan",
harga: 1500,
gambar: "tablet.png"),

ProductBox( nama:
"Flashdisk", deskripsi: "Flashdisk adalah media penyimpanan
yang berguna", harga: 100, gambar: "flashdisk.png"), ProductBox(

nama: "Floppy Drive",


deskripsi: "Floppy drive adalah media penyimpanan penyelamat yang berguna",
harga: 20, gambar: "floppy.png"),

], ));
}
}

37
Machine Translated by Google

Berdebar

class ProductBox extends StatelessWidget


{ ProductBox({Key key, this.name, this.description, this.price, this.image})
: super(kunci: kunci);

nama String akhir;


deskripsi String akhir; harga int
akhir; gambar String akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2), tinggi:
120, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[
Image.asset("assets/appimages/" + gambar),
Diperluas( anak: Kontainer( padding: EdgeInsets.all(5),
anak: Kolom( mainAxisAlignment:
MainAxisAlignment.spaceEvenly, anak:
<Widget>[ Teks(ini.nama , gaya:
TextStyle(fontWeight:

FontWeight.bold)),
Teks(ini.deskripsi),
Teks("Harga: " + ini.harga.toString()), ], )))

])));
}
}

38
Machine Translated by Google

Berdebar

Hasil akhir dari aplikasi ini adalah sebagai berikut:

39
Machine Translated by Google

8. Flutter – Pengantar Gerakan Berdebar

Gerakan pada dasarnya adalah cara bagi pengguna untuk berinteraksi dengan aplikasi seluler (atau
perangkat berbasis sentuhan apa pun). Gestur secara umum didefinisikan sebagai tindakan / gerakan
fisik apa pun dari pengguna dengan maksud untuk mengaktifkan kontrol tertentu pada perangkat seluler.
Gestur sesederhana mengetuk layar perangkat seluler hingga tindakan yang lebih kompleks yang
digunakan dalam aplikasi game.

Beberapa gerakan yang banyak digunakan disebutkan di sini:

• Ketuk: Menyentuh permukaan perangkat dengan ujung jari untuk waktu yang singkat dan kemudian
melepaskan ujung jari.

• Double Tap : Mengetuk dua kali dalam waktu singkat.

• Seret: Menyentuh permukaan perangkat dengan ujung jari lalu menggerakkan ujung jari dengan
mantap dan terakhir melepaskan ujung jari.

• Flick: Mirip dengan menyeret, tetapi melakukannya dengan cara yang lebih cepat.

• Pinch: Mencubit permukaan perangkat menggunakan dua jari.

• Spread/Zoom: Kebalikan dari mencubit.

• Panning: Menyentuh permukaan perangkat dengan ujung jari dan menggerakkannya ke segala
arah tanpa melepaskan ujung jari.

Flutter memberikan dukungan luar biasa untuk semua jenis gestur melalui widget eksklusifnya,
GestureDetector. GestureDetector adalah widget non-visual yang terutama digunakan untuk mendeteksi
gerakan pengguna. Untuk mengidentifikasi isyarat yang ditargetkan pada widget, widget dapat
ditempatkan di dalam widget GestureDetector. GestureDetector akan menangkap gestur dan mengirim
beberapa peristiwa berdasarkan gestur tersebut.

Beberapa gerakan dan acara terkait diberikan di bawah ini:

• Ketuk

o onTapDown

o onTapUp

o onTap

o onTapCancel

• Ketuk dua kali

o onDoubleTap

• Tekan lama

o onLongPress

40
Machine Translated by Google

Berdebar

• Tarik vertikal

o diVerticalDragStart

o onVerticalDragUpdate

o diVerticalDragEnd

• Tarik horizontal

o pada HorizontalDragStart

o pada HorizontalDragUpdate

o pada HorizontalDragEnd

• Pan

o onPanStart

o onPanUpdate
o onPanEnd

Sekarang, mari kita modifikasi aplikasi hello world untuk menyertakan fitur deteksi gerakan dan mencoba
memahami konsepnya.

• Ubah konten body widget MyHomePage seperti yang ditunjukkan di bawah ini:

body:
Center( anak:
GestureDetector( onTap:
() { _showDialog(konteks);
},
anak: Teks(
'Halo Dunia',
)
)
),

• Perhatikan bahwa di sini kita telah menempatkan widget GestureDetector di atas Teks
widget dalam hierarki widget, menangkap peristiwa onTap dan akhirnya menampilkan jendela
dialog.

• Terapkan fungsi *_showDialog* untuk menampilkan dialog saat pengguna mem-tab pesan halo dunia .
Ini menggunakan widget showDialog dan AlertDialog generik untuk membuat widget dialog baru.
Kode ditunjukkan di bawah ini:

// fungsi yang ditentukan


pengguna void _showDialog(Konteks BuildContext)
{ // fungsi yang ditentukan bergetar
showDialog( konteks: konteks, pembangun:
(konteks BuildContext) { // mengembalikan objek
bertipe Dialog

41
Machine Translated by Google

Berdebar

kembalikan
AlertDialog( judul: Teks
baru("Pesan"), konten: Teks baru("Halo
Dunia"), tindakan: <Widget>[ Tombol
Datar baru( anak: Teks baru("Tutup"),
onPressed: () { Navigator.
dari(konteks).pop(); }, ), ], ); }, ); }

• Aplikasi akan dimuat ulang di perangkat menggunakan fitur Hot Reload . Sekarang, cukup klik pesan,
Halo Dunia dan itu akan menampilkan dialog seperti di bawah ini:

• Sekarang, tutup dialog dengan mengklik opsi tutup di dialog.

42
Machine Translated by Google

Berdebar

• Kode lengkap (main.dart) adalah sebagai berikut:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

kembalikan MaterialApp(
title: 'Hello World Demo Application', theme:
ThemeData( primarySwatch: Colors.blue, ), home:
MyHomePage(title: 'Home page'), );

}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

// fungsi yang ditentukan


pengguna batal _showDialog(konteks BuildContext)
{ // bergetar fungsi yang ditentukan
showDialog( konteks: konteks, pembangun:
(Konteks BuildContext) { // kembalikan objek
bertipe Dialog kembalikan AlertDialog( judul:
Teks baru("Pesan"), konten: Teks baru("Halo
Dunia"), tindakan: <Widget>[ Tombol Datar
baru( anak: Teks baru("Tutup"), onPressed:
() {

Navigator.of(konteks).pop(); }, ), ], ); }, );

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title: Text(this.title), ),

43
Machine Translated by Google

Berdebar

body:
Center( anak:
GestureDetector( onTap:
() { _showDialog(konteks); },
anak: Teks(

'Halo Dunia', ))),

);
}
}

Terakhir, Flutter juga menyediakan mekanisme deteksi gestur tingkat rendah melalui widget Listener . Ini
akan mendeteksi semua interaksi pengguna dan kemudian mengirimkan peristiwa berikut:

• PointerDownEvent
• PointerMoveEvent

• PointerUpEvent
• PointerCancelEvent

Flutter juga menyediakan sekumpulan kecil widget untuk melakukan gestur spesifik dan lanjutan.
Widget tercantum di bawah ini:

• Dismissible: Mendukung gerakan jentikan untuk menutup widget.

• Draggable: Mendukung gerakan drag untuk memindahkan widget.

• LongPressDraggable: Mendukung gerakan seret untuk memindahkan widget, saat induknya


widget juga dapat diseret.

• DragTarget: Menerima widget yang dapat diseret .

• IgnorePointer: Menyembunyikan widget dan turunannya dari deteksi gerakan


proses.

• AbsorbPointer: Menghentikan proses deteksi gerakan itu sendiri sehingga setiap widget yang tumpang
tindih juga tidak dapat berpartisipasi dalam proses deteksi gerakan dan karenanya, tidak ada
peristiwa yang dimunculkan.

• Dapat digulir: Mendukung pengguliran konten yang tersedia di dalam widget

44
Machine Translated by Google

9. Flutter – Manajemen Negara Berdebar

Mengelola status dalam aplikasi adalah salah satu proses terpenting dan perlu dalam siklus hidup aplikasi.

Mari kita pertimbangkan aplikasi keranjang belanja sederhana.

• Pengguna akan login menggunakan kredensial mereka ke dalam aplikasi.

• Setelah pengguna masuk, aplikasi harus mempertahankan semua detail pengguna yang masuk
layar.

• Sekali lagi, saat pengguna memilih produk dan menyimpannya ke keranjang, informasi keranjang harus tetap ada di
antara halaman sampai pengguna memeriksa keranjang.

• Pengguna dan informasi keranjang mereka setiap saat disebut keadaan aplikasi
pada saat itu.

Manajemen status dapat dibagi menjadi dua kategori berdasarkan durasi status tertentu berlangsung dalam aplikasi.

• Ephemeral - Berlangsung selama beberapa detik seperti keadaan animasi saat ini atau satu halaman seperti peringkat
produk saat ini. Flutter mendukungnya melalui StatefulWidget.

• status aplikasi - Terakhir untuk seluruh aplikasi seperti detail pengguna yang masuk, informasi keranjang,
dll., Flutter mendukungnya melalui scoped_model.

Manajemen Negara Efemeral


Karena aplikasi Flutter terdiri dari widget, pengelolaan status juga dilakukan oleh widget. Titik masuk manajemen negara
adalah Statefulwidget. Widget dapat diwariskan dari Statefulwidget untuk mempertahankan statusnya dan status turunannya.
Statefulwidget menyediakan opsi bagi widget untuk membuat status, State<T> (di mana T adalah widget yang diwariskan)
saat widget dibuat untuk pertama kali melalui metode createState dan kemudian metode, setState untuk mengubah status
kapan pun diperlukan. Perubahan status akan dilakukan melalui gerakan. Misalnya, peringkat suatu produk dapat diubah
dengan mengetuk bintang di widget peringkat.

Mari kita buat widget, RatingBox dengan pemeliharaan negara. Tujuan dari widget ini adalah untuk menunjukkan peringkat
terkini dari produk tertentu. Proses langkah demi langkah untuk membuat widget RatingBox dengan pemeliharaan status
adalah sebagai berikut:

• Buat widget, RatingBox dengan mewarisi StatefulWidget

kelas RatingBox memperluas StatefulWidget {}

• Buat status untuk RatingBox, _RatingBoxState dengan mewarisi Status<T>

kelas _RatingBoxState memperluas Status<RatingBox> {}

45
Machine Translated by Google

Berdebar

• Ganti metode createState of StatefulWidget untuk membuat status,


_RatingBoxState

kelas RatingBox extends StatefulWidget { @override

_RatingBoxState createState() => _RatingBoxState();


}

Buat antarmuka pengguna widget RatingBox dalam metode build _RatingBoxState.


Biasanya, antarmuka pengguna akan dilakukan dalam metode build widget RatingBox itu sendiri. Namun,
saat pemeliharaan status diperlukan, kita perlu membuat antarmuka pengguna di widget _RatingBoxState.
Ini memastikan rendering ulang antarmuka pengguna setiap kali status widget diubah.

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton(

ikon: (_rating >= 1 ? Ikon(Ikon.bintang, ukuran: _ukuran,) :


Ikon(Ikon.bintang_border, ukuran: _ukuran,)), warna: Warna.merah[500], ukuran
ikon: _ukuran, ), ), Wadah( padding: EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ? Ikon(Ikon.bintang, ukuran: _ukuran,) :


Ikon(Ikon.bintang_border, ukuran: _ukuran,)), warna: Warna.merah[500], ukuran
ikon: _ukuran, ), ), Wadah( padding: EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 3 ? Ikon(Ikon.bintang, ukuran: _ukuran,) :


Ikon(Ikon.bintang_border, ukuran: _ukuran,)), warna: Warna.merah[500], ukuran
ikon: _ukuran, ), ),

], );
}

46
Machine Translated by Google

Berdebar

Di sini, kami telah menggunakan tiga bintang, dibuat menggunakan widget IconButton dan mengaturnya
menggunakan widget Baris dalam satu baris. Idenya adalah untuk menunjukkan peringkat melalui urutan bintang merah.
Misalnya, jika peringkatnya adalah dua bintang, maka dua bintang pertama berwarna merah dan yang terakhir
berwarna putih.

• Tulis metode di _RatingBoxState untuk mengubah / mengatur status widget.

batal _setRatingAsOne()
{ setState( () { _rating = 1; });

batal _setRatingAsTwo() {

setState( ()
{ _rating = 2; });

batal _setRatingAsThree()
{ setState( () { _rating = 3; });

• Di sini, setiap metode menetapkan peringkat widget saat ini melalui setState

• Sambungkan gerakan pengguna (mengetuk bintang) ke metode perubahan status yang tepat.

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton(

ikon: (_rating >= 1 ? Ikon(Icons.star, ukuran: _size,) : Ikon(Icons.star_border,


ukuran: _size,)), warna: Warna.merah[500], onPressed: _setRatingAsOne, iconSize:
_size, ), ), Container( padding: EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ? Ikon(Ikon.bintang, ukuran: _ukuran,) :


Ikon(Ikon.bintang_border, ukuran: _ukuran,)), warna: Warna.merah[500],

47
Machine Translated by Google

Berdebar

onPressed: _setRatingAsTwo,
iconSize: _size, ), ),
Container( padding: EdgeInsets.all(0),
anak: IconButton(

icon: (_rating >= 3 ? Icon(Icons.star, size: _size,) : Icon(Icons.star_border,


size: _size,)), warna: Colors.red[500], onPressed: _setRatingAsThree, iconSize:
_size, ), ),

], );
}

Di sini, event onPressed memanggil fungsi yang relevan untuk mengubah status dan selanjutnya mengubah
antarmuka pengguna. Misalnya, jika pengguna mengklik bintang ketiga, maka _setRatingAsThree akan
dipanggil dan akan mengubah _rating menjadi 3. Karena status diubah, metode build akan dipanggil lagi dan
antarmuka pengguna akan dibuat dan dirender lagi.

• Kode lengkap widget RatingBox adalah sebagai berikut:

kelas RatingBox extends StatefulWidget { @override

_RatingBoxState createState() => _RatingBoxState();


}

kelas _RatingBoxState memperluas Status<RatingBox> {


int _peringkat = 0;

batal _setRatingAsOne()
{ setState( () { _rating = 1; });

batal _setRatingAsTwo() {

setState( ()
{ _rating = 2; });

batal _setRatingAsThree()
{ setState( () { _rating = 3; });

Pembuatan widget (konteks BuildContext) {

48
Machine Translated by Google

Berdebar

ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton(

ikon: (_rating >= 1 ? Ikon(Icons.star, ukuran: _size,) :


Ikon(Icons.star_border, ukuran: _size,)), warna: Warna.merah[500], onPressed:
_setRatingAsOne, iconSize: _size, ), ), Container( padding:
EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ? Ikon(Icons.star, ukuran: _size,) :


Ikon(Icons.star_border, ukuran: _size,)), warna: Warna.merah[500], onPressed:
_setRatingAsTwo, iconSize: _size, ), ), Container( padding:
EdgeInsets.all(0), anak: IconButton(

icon: (_rating >= 3 ? Icon(Icons.star, size: _size,) : Icon(Icons.star_border,


size: _size,)), warna: Colors.red[500], onPressed: _setRatingAsThree, iconSize:
_size, ), ),

], );
}
}

Mari kita buat aplikasi baru dan gunakan widget RatingBox yang baru kita buat untuk menunjukkan peringkat
produk.

• Buat aplikasi Flutter baru di studio Android, product_state_app

Ganti kode main.dart dengan kode di bawah ini:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

49
Machine Translated by Google

Berdebar

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product state
demo home page'), );

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:

Teks(
'Halo Dunia', )),

);
}
}

• Di Sini,

• Kami telah membuat widget MyHomePage dengan memperluas StatelessWidget sebagai gantinya
default StatefulWidget dan kemudian menghapus kode yang relevan.

• Sertakan widget RatingBox kami yang baru dibuat.

• Buat widget ProductBox untuk mencantumkan produk beserta peringkat seperti yang ditentukan di bawah ini:

class ProductBox extends StatelessWidget


{ ProductBox({Key key, this.name, this.description, this.price, this.image}) :
super(key: key);

nama String akhir;


deskripsi String akhir; harga int
akhir; gambar String akhir;

Bangun widget (konteks BuildContext) { return


Container (

50
Machine Translated by Google

Berdebar

padding: EdgeInsets.all(2), tinggi:


120, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[
Image.asset("assets/appimages/" + gambar),
Diperluas( anak: Kontainer( padding: EdgeInsets.all(5),
anak: Kolom( mainAxisAlignment:

MainAxisAlignment.spaceMerata,
anak-anak:
<Widget>[ Text(ini.nama,
gaya: TextStyle(fontWeight:
FontWeight.bold)),
Text(this.description),
Text("Harga: " + this.price.toString()), RatingBox(), ], )))

])));
}
}

• Perbarui widget MyHomePage untuk menyertakan widget ProductBox seperti yang ditentukan
di bawah:

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Listing")), body: ListView( shrinkWrap: true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , anak-anak:
<Widget>[ ProductBox( nama: "iPhone", deskripsi: "iPhone
adalah ponsel stylist yang pernah ada", harga: 1000, gambar: "iphone.png"),
ProductBox( nama: "Pixel", deskripsi: " Pixel adalah ponsel paling berfitur
yang pernah ada", harga: 800, gambar: "pixel.png"), ProductBox( nama:
"Laptop", deskripsi: "Laptop adalah alat pengembangan paling
produktif",

51
Machine Translated by Google

Berdebar

harga: 2000,
gambar: "laptop.png"),

ProductBox( nama:
"Tablet", deskripsi: "Tablet adalah perangkat paling berguna yang pernah ada
pertemuan",
harga: 1500,
gambar: "tablet.png"),

ProductBox( nama:
"Flashdisk", deskripsi: "Flashdisk adalah media penyimpanan
yang berguna", harga: 100, gambar: "flashdisk.png"),

Kotak Produk(
nama: "Floppy Drive",
deskripsi: "Floppy drive adalah penyimpanan penyelamat yang berguna
sedang",
harga: 20,
gambar: "floppy.png"),

], ));
}
}

• Kode lengkap aplikasi adalah sebagai berikut:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product layout
demo home page'), );

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@mengesampingkan

Pembuatan widget(konteks BuildContext) { return


Scaffold( appBar: AppBar(judul: Teks("Daftar
Produk")), body: ListView(

52
Machine Translated by Google

Berdebar

shrinkWrap: true,
padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0), anak-anak:
<Widget>[ ProductBox( nama: "iPhone", deskripsi: "iPhone adalah ponsel
stylist yang pernah ada", harga: 1000, gambar : "iphone.png"),

ProductBox( nama:
"Pixel", deskripsi: "Pixel adalah ponsel paling berfitur yang pernah ada",
harga: 800, gambar: "pixel.png"), ProductBox( nama: "Laptop", deskripsi:
"Laptop adalah alat pengembangan paling produktif ", harga: 2000,
gambar: "laptop.png"),

ProductBox( nama:
"Tablet", deskripsi: "Tablet adalah perangkat paling berguna yang pernah ada
pertemuan",
harga: 1500,
gambar: "tablet.png"),

ProductBox( nama:
"Flashdisk", deskripsi: "iPhone adalah ponsel stylist yang
pernah ada", harga: 100, gambar: "pendrive.png"), ProductBox(

nama: "Floppy Drive",


deskripsi: "iPhone adalah ponsel stylist yang pernah ada",
harga: 20, gambar: "floppy.png"),

ProductBox( nama:
"iPhone", deskripsi: "iPhone adalah ponsel stylist yang pernah
ada", harga: 1000, gambar: "iphone.png"),

ProductBox( nama:
"iPhone", deskripsi: "iPhone adalah ponsel stylist yang pernah
ada", harga: 1000, gambar: "iphone.png"),

], ));
}
}

kelas RatingBox extends StatefulWidget { @override

_RatingBoxState createState() => _RatingBoxState();


}

kelas _RatingBoxState memperluas Status<RatingBox> {

53
Machine Translated by Google

Berdebar

int _peringkat = 0;

batal _setRatingAsOne()
{ setState( () { _rating = 1; });

batal _setRatingAsTwo() {

setState( ()
{ _rating = 2; });

batal _setRatingAsThree()
{ setState( () { _rating = 3; });

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton(

ikon: (_rating >= 1 ? Ikon(Icons.star, ukuran: _size,) :


Ikon(Icons.star_border, ukuran: _size,)), warna: Warna.merah[500], onPressed:
_setRatingAsOne, iconSize: _size, ), ), Container( padding:
EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ? Ikon(Icons.star, ukuran: _size,) :


Ikon(Icons.star_border, ukuran: _size,)), warna: Warna.merah[500], onPressed:
_setRatingAsTwo, iconSize: _size, ), ), Container( padding:
EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 3 ? Ikon(Ikon.bintang, ukuran: _ukuran,) :


Ikon(Ikon.bintang_border, ukuran: _ukuran,)),

54
Machine Translated by Google

Berdebar

warna: Warna.merah[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ),

], );
}
}

class ProductBox extends StatelessWidget


{ ProductBox({Key key, this.name, this.description, this.price, this.image}) :
super(key: key);

nama String akhir;


deskripsi String akhir; harga int
akhir; gambar String akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2), tinggi:
140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[
Image.asset("assets/appimages/" + gambar),
Diperluas( anak: Kontainer( padding: EdgeInsets.all(5),
anak: Kolom( mainAxisAlignment:

MainAxisAlignment.spaceMerata,
anak-anak:
<Widget>[ Text(ini.nama,
gaya: TextStyle(fontWeight:
FontWeight.bold)),
Text(this.description),
Text("Harga: " + this.price.toString()), RatingBox(), ], )))

])));
}
}

55
Machine Translated by Google

Berdebar

• Terakhir, jalankan aplikasi dan lihat halaman State management - Product list
Hasil seperti yang ditunjukkan di sini:

56
Machine Translated by Google

Berdebar

Mengklik bintang peringkat akan memperbarui peringkat produk. Misalnya, pengaturan peringkat 2 bintang
untuk iPhone akan menampilkan peringkat seperti di bawah ini:

Status Aplikasi -scoped_model


Flutter menyediakan cara mudah untuk mengelola status aplikasi menggunakan paket scoped_model. Paket
Flutter hanyalah pustaka dari fungsionalitas yang dapat digunakan kembali. Kita akan belajar tentang paket
Flutter secara mendetail di bab mendatang.

scoped_model menyediakan tiga kelas utama untuk mengaktifkan manajemen status yang kuat dalam aplikasi
yang dibahas secara mendetail di sini:

Model
Model merangkum keadaan aplikasi. Kita dapat menggunakan Model sebanyak mungkin (dengan mewarisi
kelas Model) sesuai kebutuhan untuk mempertahankan status aplikasi. Ia memiliki metode tunggal,
notifyListeners, yang perlu dipanggil setiap kali status Model berubah. notifyListeners akan melakukan hal-hal
yang diperlukan untuk memperbarui UI.

kelas Produk meluas Model { nama


String akhir; deskripsi String akhir;
harga int akhir;

57
Machine Translated by Google

Berdebar

gambar String akhir;


peringkat int;

Produk(ini.nama, deskripsi ini, harga ini, gambar ini, peringkat ini);

pabrik Product.fromMap(Map<String, dynamic> json) { return


Product( json['name'], json['description'], json['price'], json['image'],
json['rating' ], );

void updateRating(int myRating) {


peringkat = peringkatku;

notifyListeners();
}
}

ScopedModel
ScopedModel adalah sebuah widget, yang menyimpan model yang diberikan dan meneruskannya ke semua
widget turunan jika diminta. Jika diperlukan lebih dari satu model, maka kita perlu menyarangkan
ScopedModel.

• Model tunggal

ScopedModel<Produk>( model:
item, anak: AnyWidget()

• Model ganda

ScopedModel<Produk>( model:
item1, anak:
ScopedModel<Produk>( model:
item2, anak: AnyWidget(), ),

ScopedModel.of adalah metode yang digunakan untuk mendapatkan model yang mendasari ScopedModel.
Ini dapat digunakan saat tidak ada perubahan UI yang diperlukan meskipun model akan berubah. Berikut ini
tidak akan mengubah UI (peringkat) produk.

ScopedModel.of<Produk>(konteks).updateRating(2);

58
Machine Translated by Google

Berdebar

ScopedModelDescendant
ScopedModelDescendant adalah widget, yang mendapatkan model dari widget tingkat atas, ScopedModel, dan
membangun antarmuka penggunanya setiap kali model berubah.

ScopedModelDescendant memiliki dua properti – pembangun dan anak. anak adalah bagian UI yang tidak berubah
dan akan diteruskan ke pembangun. builder menerima fungsi dengan tiga argumen:

• konten - ScopedModelDescendant meneruskan konteks aplikasi.

• anak - Bagian dari UI, yang tidak berubah berdasarkan model.


• model - Model aktual pada saat itu.

kembalikan ScopedModelDescendant<ProductModel>(
pembangun: (konteks, anak, keranjang) => { ... UI Aktual ... }, anak: PartOfTheUI(), );

Mari kita ubah sampel kita sebelumnya untuk menggunakan scoped_model daripada StatefulWidget

• Buat aplikasi Flutter baru di studio Android, product_scoped_model_app

• Ganti kode startup default (main.dart) dengan kode product_state_app kami.

• Salin folder aset dari product_nav_app ke product_rest_app dan tambahkan aset


di dalam file pubspec.yaml

berdebar:

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/pendrive.png
- aset/appimages/pixel.png - aset/appimages/
tablet.png

• Konfigurasikan paket scoped_model pada file pubspec.yaml seperti gambar di bawah ini:

dependensi:
scoped_model: ^1.0.1

Di sini, Anda harus menggunakan paket http versi terbaru

• Android studio akan memberi tahu bahwa pubspec.yaml telah diperbarui.

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan mengonfigurasinya
dengan benar untuk aplikasi tersebut.

59
Machine Translated by Google

Berdebar

• Ganti kode startup default (main.dart) dengan kode startup kami.

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product state
demo home page'), );

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
Text( 'Hello World', )),

);
}
}

• Impor paket scoped_model di file main.dart

import 'package:scoped_model/scoped_model.dart';

• Mari kita buat kelas Produk, Product.dart untuk mengatur informasi produk.

import 'package:scoped_model/scoped_model.dart';

kelas Produk meluas Model { nama


String akhir; deskripsi String akhir;
harga int akhir; gambar String akhir;
peringkat int;

60
Machine Translated by Google

Berdebar

Produk(ini.nama, ini.deskripsi, ini.harga, ini.gambar,


this.rating);

pabrik Product.fromMap(Map<String, dynamic> json) { return


Product( json['name'], json['description'], json['price'], json['image'],
json['rating' ], );

void updateRating(int myRating) {


peringkat = peringkatku;

notifyListeners();
}
}

Di sini, kami menggunakan notifyListeners untuk mengubah UI setiap kali peringkat diubah.

• Mari kita tulis metode getProducts di kelas Produk untuk menghasilkan dummy kita
catatan produk.

Daftar statis<Produk> getProduk() {


Daftar<Produk> item = <Produk>[];

items.add(Product( "Pixel",
"Pixel adalah
ponsel paling lengkap fitur yang pernah ada", 800,
"pixel.png", 0));

items.add(Product( "Laptop", "Laptop adalah alat pengembangan


paling produktif", 2000, "laptop.png", 0));

items.add(Product( "Tablet", "Tablet adalah perangkat yang paling


berguna untuk rapat", 1500, "tablet.png", 0));

items.add(Product( "Flashdisk", "Flashdisk adalah


media penyimpanan yang berguna", 100,
"Flashdisk.png", 0));

item.tambahkan(Produk(

61
Machine Translated by Google

Berdebar

"Floppy Drive",
"Floppy drive adalah media penyimpanan penyelamat yang
berguna", 20, "floppy.png", 0));

mengembalikan barang;

}
impor product.dart di main.dart
impor 'Produk.dart';

• Mari kita ubah widget baru kita, RatingBox untuk mendukung konsep scoped_model.

kelas RatingBox extends StatelessWidget


{ RatingBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
print(item.rating);

return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton( icon: (item.rating >= 1 ? Ikon(Ikon.bintang,
ukuran: _ukuran,

)
:
Ikon( Icons.star_border,
size: _size, )), warna:
Colors.red[500],
onPressed: () =>
this.item.updateRating(1), iconSize: _size, ), ),
Container( padding: EdgeInsets.all(0), anak:
IconButton( icon: (item.rating >= 2 ? Icon( Icons.star,
ukuran: _size,

)
:
Ikon( Icons.star_border,
ukuran: _size,

62
Machine Translated by Google

Berdebar

)),
warna: Colors.red[500],
onPressed: () => this.item.updateRating(2), iconSize:
_size, ), ), Container( padding: EdgeInsets.all(0), child:
IconButton( ikon: (item.rating >= 3 ? Ikon( Bintang ikon,
ukuran: _ukuran,

)
:
Ikon( Ikon.bintang_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: () =>
this.item.updateRating(3), ukuran ikon: _ukuran, ), ], );

}
}

Di sini, kami telah memperluas RatingBox dari StatelessWidget, bukan StatefulWidget.


Selain itu, kami telah menggunakan metode updateRating model Produk untuk menetapkan peringkat.

• Mari kita memodifikasi widget ProductBox kita untuk bekerja dengan Product, ScopedModel dan
Kelas ScopedModelDescendant.

kelas ProductBox meluas StatelessWidget {


ProductBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2),
tinggi: 140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[ Image.asset("assets/appimages/" +
this.item.image), Diperluas( anak: Kontainer( padding:
EdgeInsets.all(5), anak: ScopedModel<Produk >( model: this.item,
anak: Kolom(

63
Machine Translated by Google

Berdebar

mainAxisAlignment:
MainAxisAlignment.spaceEvenly, anak-anak: <Widget>[

Teks(nama.item.ini, gaya:
TextStyle(Berat font:

FontWeight.bold)),
Teks(ini.item.deskripsi), Teks("Harga:
" +
this.item.price.toString()),
ScopedModelDescendant<Produk>(
pembangun: (konteks, anak, item) {
return RatingBox(item: item); }) ], ))))

]),
));
}
}

Di sini, kami telah menggabungkan widget RatingBox di dalam ScopedModel dan ScopedModelDecendant.

• Ubah widget MyHomePage untuk menggunakan widget ProductBox kami.

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

item akhir = Product.getProducts();

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Navigation")), body: ListView.builder(

itemCount: items.length,
itemBuilder: (konteks, indeks) { return
ProductBox(item: item[indeks]); }, ));

}
}

Di sini, kami telah menggunakan ListView.builder untuk membuat daftar produk kami secara dinamis.

• Kode lengkap aplikasi adalah sebagai berikut:

Produk.dart

import 'package:scoped_model/scoped_model.dart';

kelas Produk memperluas Model {

64
Machine Translated by Google

Berdebar

nama String akhir;


deskripsi String akhir; harga int
akhir; gambar String akhir;
peringkat int;

Produk(ini.nama, deskripsi ini, harga ini, gambar ini, peringkat ini);

pabrik Product.fromMap(Map<String, dynamic> json) { return


Product( json['name'], json['description'], json['price'], json['image'],
json['rating' ], );N

batal cn
"Laptop adalah alat pengembangan paling produktif", 2000,
"laptop.png", 0));

items.add(Product( "Tablet"cnvn, "Tablet adalah perangkat yang paling


berguna untuk rapat", 1500, "tablet.png", 0));

items.add(Product( "Flashdisk", "Flashdisk adalah


media penyimpanan yang berguna", 100,
"Flashdisk.png", 0));

items.add(Product( "Floppy
Drive", "Floppy
drive adalah media penyimpanan penyelamat yang berguna",
20, "floppy.png", 0));

mengembalikan barang;
}
}
main.dart

import 'package:flutter/material.dart'; import


'package:scoped_model/scoped_model.dart'; impor 'Produk.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda.

65
Machine Translated by Google

Berdebar

@mengesampingkan

Pembuatan widget (konteks BuildContext) {


return MaterialApp( title:
'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product state
demo home page'), );

}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

item akhir = Product.getProducts();

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Navigation")), body: ListView.builder(

itemCount: items.length,
itemBuilder: (konteks, indeks) { return
ProductBox(item: item[indeks]); }, ));

}
}

kelas RatingBox memperluas StatelessWidget {


RatingBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
print(item.rating);

return
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton( icon: (item.rating >= 1 ? Ikon(Ikon.bintang,
ukuran: _ukuran,

)
: Ikon(

66
Machine Translated by Google

Berdebar

Icons.star_border,
size: _size, )), color:
Colors.red[500],
onPressed: () =>
this.item.updateRating(1), iconSize: _size, ), ),
Container( padding: EdgeInsets.all (0), anak:
IconButton( icon: (item.rating >= 2 ? Icon( Icons.star,
ukuran: _size,

)
:
Ikon( Icons.star_border,
size: _size, )), warna:
Colors.red[500],
onPressed: () =>
this.item.updateRating(2), iconSize: _size, ), ),
Container( padding: EdgeInsets.all(0), anak:
IconButton( icon: (item.rating >= 3 ? Icon( Icons.star,
ukuran: _size,

)
:
Ikon( Ikon.bintang_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: () =>
this.item.updateRating(3), ukuran ikon: _ukuran, ), ], );

}
}

kelas ProductBox meluas StatelessWidget {


ProductBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Bangun widget (konteks BuildContext)


{ kembalikan Wadah ( padding: EdgeInsets.all
(2),

67
Machine Translated by Google

Berdebar

tinggi: 140,
anak:
Kartu( anak: Baris(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-
anak: <Widget>[ Image.asset("assets/appimages/" +
this.item.image), Diperluas( anak: Kontainer( padding:
EdgeInsets.all(5), anak: ScopedModel<Produk >( model:
this.item, anak: Kolom( mainAxisAlignment:
MainAxisAlignment.spaceEvenly, anak: <Widget>[

Teks(nama.item.ini,
gaya: TextStyle(Berat
font:
FontWeight.bold)),
Teks(ini.item.deskripsi),
Teks("Harga: " +
this.item.price.toString()),
ScopedModelDescendant<Produk>(
pembangun: (konteks, anak, item) {
return RatingBox(item: item); }) ], ))))

]),
));
}
}

Terakhir, kompilasi dan jalankan aplikasi untuk melihat hasilnya. Ini akan bekerja mirip dengan contoh
sebelumnya kecuali aplikasi menggunakan konsep scoped_model.

Navigasi dan Perutean


Dalam aplikasi apa pun, menavigasi dari satu halaman/layar ke halaman lain menentukan alur kerja
aplikasi. Cara navigasi aplikasi ditangani disebut Routing.
Flutter menyediakan kelas perutean dasar – MaterialPageRoute dan dua metode – Navigator.push dan
Navigator.pop, untuk menentukan alur kerja aplikasi.

MaterialPageRoute
MaterialPageRoute adalah widget yang digunakan untuk merender UI-nya dengan mengganti seluruh layar
dengan animasi khusus platform.

MaterialPageRoute(pembangun: (konteks) => Widget())

Di sini, pembangun akan menerima fungsi untuk membangun kontennya dengan melengkapi konteks
aplikasi saat ini.

Navigasi.push

68
Machine Translated by Google

Berdebar

Navigation.push digunakan untuk menavigasi ke layar baru menggunakan widget MaterialPageRoute.

Navigator.push( konteks,

MaterialPageRoute(pembangun: (konteks) => Widget()),


);

Navigasi.pop
Navigation.pop digunakan untuk menavigasi ke layar sebelumnya.

Navigator.push(konteks);

Mari kita buat aplikasi baru untuk lebih memahami konsep navigasi.

Buat aplikasi Flutter baru di studio Android, product_nav_app

• Salin folder aset dari product_nav_app ke product_state_app dan tambahkan aset


di dalam file pubspec.yaml

berdebar:

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/
pendrive.png - aset/appimages/pixel.png -
aset/appimages/tablet.png

• Ganti kode startup default (main.dart) dengan kode startup kita.

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget build(Konteks
BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product state demo
home page'), );

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

69
Machine Translated by Google

Berdebar

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
Text( 'Hello World', )),

);
}
}

• Mari kita buat kelas Produk untuk mengatur informasi produk.

kelas Produk
{ nama String akhir;
deskripsi String akhir; harga int
akhir; gambar String akhir;

Produk(ini.nama, ini.deskripsi, ini.harga, ini.gambar);


}

• Mari kita tulis metode getProducts di kelas Produk untuk menghasilkan dummy kita
catatan produk.

Daftar statis<Produk> getProduk() {


Daftar<Produk> item = <Produk>[];

items.add(Product( "Pixel",
"Pixel adalah
ponsel dengan fitur paling lengkap", 800, "pixel.png"));

items.add(Product( "Laptop", "Laptop adalah alat pengembangan


paling produktif", 2000, "laptop.png"));

items.add(Product( "Tablet",
"Tablet adalah
perangkat yang paling berguna untuk rapat", 1500, "tablet.png"));

items.add(Product( "Flashdisk", "Flashdisk adalah media penyimpanan yang berguna",

70
Machine Translated by Google

Berdebar

100,
"pendrive.png"));

items.add(Product( "Floppy
Drive", "Floppy
drive adalah media penyimpanan penyelamat yang berguna",
20, "floppy.png"));

mengembalikan barang;
}
impor product.dart di main.dart

impor 'Produk.dart';

• Mari sertakan widget baru kita, RatingBox

kelas RatingBox extends StatefulWidget { @override

_RatingBoxState createState() => _RatingBoxState();


}

kelas _RatingBoxState memperluas Status<RatingBox> {


int _peringkat = 0;

batal _setRatingAsOne()
{ setState(() { _rating = 1; });

batal _setRatingAsTwo()
{ setState(() { _rating = 2; });

batal _setRatingAsThree() {
setState(()
{ _rating = 3; });

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0), anak:
IconButton(

71
Machine Translated by Google

Berdebar

ikon: (_rating >= 1 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsOne,
iconSize: _size, ), ),
Container( padding:
EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsTwo,
iconSize: _size, ), ),
Wadah( padding: EdgeInsets.all(0),
anak: IconButton(

ikon: (_rating >= 3 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ), ], );

}
}

72
Machine Translated by Google

Berdebar

• Mari kita memodifikasi widget ProductBox kita untuk bekerja dengan kelas Produk baru kita.

kelas ProductBox extends StatelessWidget


{ ProductBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2), tinggi:
140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[ Image.asset("assets/appimages/" +
this.item.image), Diperluas( anak: Kontainer( padding:
EdgeInsets.all(5), anak: Kolom( mainAxisAlignment :
MainAxisAlignment.spaceEvenly,

anak-anak: <Widget>[
Teks(nama.item.ini, gaya:
TextStyle(Berat font:
FontWeight.bold)),
Text(this.item.description),
Text("Harga: " + this.item.price.toString()), RatingBox(), ], )))

]),
));
}
}

• Mari kita menulis ulang widget MyHomePage kita untuk bekerja dengan model Produk dan untuk membuat daftar
semua produk menggunakan ListView.

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

item akhir = Product.getProducts();

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Navigation")), body: ListView.builder(

itemCount: item.panjang,
itemBuilder: (konteks, indeks) {

73
Machine Translated by Google

Berdebar

return GestureDetector( anak:


ProductBox(item: item[indeks]), onTap: ()
{ Navigator.push( konteks, MaterialPageRoute(

pembangun: (konteks) => ProductPage(item:


item[indeks]),

), ); }, ); }, ));

}
}

Di sini, kami telah menggunakan MaterialPageRoute untuk menavigasi ke halaman detail produk.

• Sekarang, mari kita tambahkan ProductPage untuk menampilkan detail produk.

kelas ProductPage memperluas StatelessWidget {


ProductPage({Key key, this.item}) : super(key: key);

item Produk akhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.item.name), ), body: Center( child:
Container( padding: EdgeInsets.all(0),

anak:
Kolom( mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, anak:
<Widget>[ Image.asset("assets/appimages/" +

this.item.image),

Diperluas( anak:
Kontainer( padding: EdgeInsets.all(5),
anak: Kolom( mainAxisAlignment:

MainAxisAlignment.spaceMerata,
anak-anak: <Widget>[
Teks(nama.item.ini, gaya:
TextStyle(Berat font:
FontWeight.bold)),
Teks(ini.item.deskripsi), Teks("Harga:
" +
this.item.price.toString()),
RatingBox(),

74
Machine Translated by Google

Berdebar

], )))
]),
),

), );
}
}

• Kode lengkap aplikasi adalah sebagai berikut:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

kelas Produk
{ nama String akhir;
deskripsi String akhir; harga int
akhir; gambar String akhir;

Produk(ini.nama, ini.deskripsi, ini.harga, ini.gambar);

Daftar statis<Produk> getProduk() {


Daftar<Produk> item = <Produk>[];

items.add(Product( "Pixel",
"Pixel adalah ponsel paling berfitur yang pernah ada", 800,
"piksel.png"));

items.add(Product("Laptop", "Laptop adalah alat pengembangan paling produktif",

2000, "laptop.png"));

items.add(Product( "Tablet",
"Tablet adalah
perangkat yang paling berguna untuk rapat", 1500, "tablet.png"));

items.add(Product( "Pendrive", "iPhone adalah ponsel paling bergaya",


100, "pendrive.png"));

items.add(Product( "Floppy
Drive", "iPhone adalah ponsel stylist yang pernah ada", 20, "floppy.png"));

items.add(Product( "iPhone", "iPhone adalah ponsel stylist yang pernah


ada", 1000, "iphone.png"));

mengembalikan barang;
}
}

75
Machine Translated by Google

Berdebar

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Product Navigation
demo home page'), );

}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

item akhir = Product.getProducts();

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Navigation")), body: ListView.builder(

itemCount: items.length,
itemBuilder: (konteks, indeks) { return
GestureDetector( anak:
ProductBox(item: item[indeks]), onTap: ()
{ Navigator.push( konteks, MaterialPageRoute(

pembangun: (konteks) => ProductPage(item:


item[indeks]),

), ); }, ); }, ));

}
}

kelas ProductPage memperluas StatelessWidget {


ProductPage({Key key, this.item}) : super(key: key);

item Produk akhir;

@mengesampingkan

Pembuatan widget(konteks BuildContext)


{ return Scaffold( appBar: AppBar(

76
Machine Translated by Google

Berdebar

title: Text(this.item.name), ), body:


Center( child: Container( padding:
EdgeInsets.all(0), child:
Column( mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start, children: <Widget
>[ Image.asset("assets/appimages/" + this.item.image),
Diperluas( child: Container( padding: EdgeInsets.all(5),
child: Column( mainAxisAlignment:

MainAxisAlignment.spaceMerata,
anak-anak: <Widget>[
Teks(nama.item.ini, gaya:
TextStyle(Berat font:
FontWeight.bold)),
Teks(ini.item.deskripsi), Teks("Harga:
" +
this.item.price.toString()),
RatingBox(), ], )))

]),
),

), );
}
}

kelas RatingBox extends StatefulWidget { @override

_RatingBoxState createState() => _RatingBoxState();


}

kelas _RatingBoxState memperluas Status<RatingBox> {


int _peringkat = 0;

batal _setRatingAsOne()
{ setState(() { _rating = 1; });

batal _setRatingAsTwo()
{ setState(() { _rating = 2; });

batal _setRatingAsThree()
{ setState(() {

77
Machine Translated by Google

Berdebar

_peringkat =
3; });
}

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0),
anak: IconButton(

ikon: (_rating >= 1 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsOne,
iconSize: _size, ), ),
Container( padding:
EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsTwo,
iconSize: _size, ), ),
Wadah( padding: EdgeInsets.all(0),
anak: IconButton(

ikon: (_rating >= 3 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)

78
Machine Translated by Google

Berdebar

:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ), ], );

}
}

kelas ProductBox meluas StatelessWidget {


ProductBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2),
tinggi: 140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[ Image.asset("assets/appimages/" +
this.item.image), Diperluas( anak: Kontainer( padding:
EdgeInsets.all(5), anak: Kolom( mainAxisAlignment :
MainAxisAlignment.spaceEvenly, anak-anak: <Widget>[

Teks(nama.item.ini, gaya:
TextStyle(Berat font:
FontWeight.bold)),
Text(this.item.description),
Text("Harga: " + this.item.price.toString()), RatingBox(), ], )))

]),
));
}
}

79
Machine Translated by Google

Berdebar

Jalankan aplikasi dan klik salah satu item produk. Ini akan menampilkan halaman detail yang relevan. Kita bisa pindah
ke halaman rumah dengan mengklik tombol kembali. Halaman daftar produk dan halaman detail produk aplikasi
ditampilkan sebagai berikut:

80
Machine Translated by Google

Berdebar

81
Machine Translated by Google

10. Flutter – Animasi Berdebar

Animasi adalah prosedur kompleks dalam aplikasi seluler apa pun. Terlepas dari kerumitannya,
Animasi meningkatkan pengalaman pengguna ke tingkat yang baru dan menyediakan interaksi
pengguna yang kaya. Karena kekayaannya, animasi menjadi bagian integral dari aplikasi seluler
modern. Kerangka kerja Flutter mengakui pentingnya Animasi dan menyediakan kerangka kerja yang
sederhana dan intuitif untuk mengembangkan semua jenis animasi.

Perkenalan
Animasi adalah proses menampilkan rangkaian gambar/gambar dalam urutan tertentu dalam durasi
tertentu untuk memberikan ilusi gerakan. Aspek yang paling penting dari animasi adalah sebagai
berikut:

• Animasi memiliki dua nilai yang berbeda: nilai awal dan nilai akhir. Animasi dimulai dari nilai Mulai
dan melewati serangkaian nilai perantara dan akhirnya berakhir pada nilai Akhir . Misalnya,
untuk menganimasikan widget agar menghilang, nilai awal adalah opasitas penuh dan nilai akhir
adalah opasitas nol.

• Nilai-nilai perantara mungkin bersifat linier atau non-linier (kurva) dan dapat dikonfigurasi. Pahami
bahwa animasi berfungsi seperti yang dikonfigurasi. Setiap konfigurasi memberikan nuansa
berbeda pada animasi. Misalnya, memudar widget akan bersifat linier sedangkan pantulan bola
akan bersifat non-linier.

• Durasi proses animasi mempengaruhi kecepatan (slowness atau fastness) dari animasi tersebut
animasi.

• Kemampuan untuk mengontrol proses animasi seperti memulai animasi, menghentikan animasi,
mengulang animasi untuk mengatur berapa kali, membalikkan proses animasi, dll.,

• Di Flutter, sistem animasi tidak melakukan animasi nyata. Alih-alih, ini hanya memberikan nilai
yang diperlukan di setiap bingkai untuk merender gambar.

Kelas Berbasis Animasi


Sistem animasi Flutter didasarkan pada objek Animasi. Kelas animasi inti dan penggunaannya
adalah sebagai berikut:

Animasi
Menghasilkan nilai interpolasi antara dua angka selama durasi tertentu. Kelas Animasi yang paling
umum adalah:

• Animation<double> - menyisipkan nilai antara dua angka desimal

• Animation<Color> - menyisipkan warna antara dua warna

• Animation<Size> - menyisipkan ukuran antara dua ukuran

82
Machine Translated by Google

Berdebar

• AnimationController - Objek Animasi Khusus untuk mengontrol animasi itu sendiri. Ini menghasilkan nilai baru setiap
kali aplikasi siap untuk bingkai baru. Ini mendukung animasi berbasis linier dan nilainya mulai dari 0,0 hingga 1,0.

controller = AnimationController(durasi: durasi const(detik: 2), vsync: ini);

Di sini, pengontrol mengontrol animasi dan opsi durasi mengontrol durasi proses animasi. vsync adalah opsi
khusus yang digunakan untuk mengoptimalkan sumber daya yang digunakan dalam animasi.

CurvedAnimation
Mirip dengan AnimationController tetapi mendukung animasi non-linear. CurvedAnimation dapat digunakan bersama
dengan objek Animation seperti di bawah ini:

controller = AnimationController(durasi: durasi const(detik: 2), vsync: ini); animasi = CurvedAnimation(induk:


pengontrol, kurva: Curves.easeIn)

Dua <T>
Berasal dari Animatable<T> dan digunakan untuk menghasilkan angka antara dua angka selain 0 dan 1. Ini dapat
digunakan bersama dengan objek Animation dengan menggunakan metode animate dan meneruskan objek Animation
yang sebenarnya.

Pengontrol AnimationController = AnimationController(


durasi: Durasi const (milidetik: 1000), vsync: ini); Animasi<int> customTween =
IntTween(awal: 0, akhir: 255).animate(pengontrol);

Tween juga dapat digunakan bersama dengan CurvedAnimation seperti di bawah ini:

Pengontrol AnimationController = AnimationController(durasi: Durasi const(milidetik: 500), vsync: ini);


kurva Animasi akhir = CurvedAnimation(induk: pengontrol, kurva: Curves.easeOut); Animasi<int>
customTween = IntTween(awal: 0, akhir: 255).animate(curve);

Di sini, pengontrol adalah pengontrol animasi yang sebenarnya. kurva memberikan jenis non-linearitas dan customTween
menyediakan rentang kustom dari 0 hingga 255.

Alur kerja FlutterAnimation


Alur kerja animasi adalah sebagai berikut:

• Tentukan dan jalankan pengontrol animasi di initState dari StatefulWidget.

AnimationController(durasi: Durasi const(detik: 2), vsync: ini); animasi = Tween<double>(mulai: 0, akhir:


300).animate(pengontrol); controller.maju();

• Tambahkan pendengar berbasis animasi, addListener untuk mengubah status widget

83
Machine Translated by Google

Berdebar

animation = Tween<double>(begin: 0, end: 300).animate(controller) ..addListener(()


{ setState(() { // Keadaan yang berubah di sini adalah objek animasi

nilai. });

});

Widget bawaan, AnimatedWidget dan AnimatedBuilder dapat digunakan untuk melewati proses ini. Kedua
widget menerima objek Animasi dan mendapatkan nilai saat ini yang diperlukan untuk animasi.

• Dapatkan nilai animasi selama proses pembuatan widget, lalu terapkan untuk lebar, tinggi, atau properti apa
pun yang relevan, bukan nilai aslinya.

anak: Wadah( tinggi:


animasi.nilai, lebar: nilai animasi,
anak: <Widget>,

Aplikasi Kerja
Mari kita menulis aplikasi berbasis animasi sederhana untuk memahami konsep animasi dalam framework Flutter.

• Buat aplikasi Flutter baru di studio Android, product_animation_app

• Salin folder aset dari product_nav_app ke product_animation_app dan tambahkan aset di dalam file
pubspec.yaml

berdebar:

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/
pendrive.png - aset/appimages/pixel.png -
aset/appimages/tablet.png

• Hapus kode startup default (main.dart).

• Tambahkan impor dan fungsi utama dasar

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

• Buat widget MyApp yang berasal dari StatefulWidgtet

kelas MyApp memperluas StatefulWidget {


_MyAppState createState() => _MyAppState(); }

84
Machine Translated by Google

Berdebar

• Buat widget _MyAppState dan implementasikan initState dan buang selain metode build default.

kelas _MyAppState memperluas Status<MyApp> dengan SingleTickerProviderStateMixin {

Animasi<double> animasi;
Pengontrol AnimationController;

@override
void initState() {
super.initState();
controller = AnimationController(durasi: Durasi const(detik: 10), vsync: ini);

animasi = Tween<double>(mulai: 0.0, akhir: 1.0).animate(pengontrol); controller.maju();

// Widget ini adalah root dari aplikasi Anda. @override Widget


build(BuildContext context) { controller.forward(); kembalikan
MaterialApp( judul: 'Flutter Demo', tema:
ThemeData( primarySwatch: Colors.blue, ), beranda:
MyHomePage( judul: 'Halaman beranda demo tata letak
produk', animasi: animasi,)

);
}

@override
void buang()
{ controller.dispose();
super.buang();
}
}

Di Sini,

• Dalam metode initState, kami telah membuat objek pengontrol animasi (controller), objek animasi
(animation) dan memulai animasi menggunakan controller.forward.

• Dalam metode buang, kita telah membuang objek pengendali animasi (controller).

• Dalam metode build, kirim animasi ke widget MyHomePage melalui konstruktor. Sekarang, widget
MyHomePage dapat menggunakan objek animasi untuk menganimasikan kontennya.

• Sekarang, tambahkan widget ProductBox

class ProductBox extends StatelessWidget


{ ProductBox({Key key, this.name, this.description, this.price, this.image})

85
Machine Translated by Google

Berdebar

: super(kunci: kunci);

nama String akhir;


deskripsi String akhir; harga int
akhir; gambar String akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2), tinggi:
140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak:


<Widget>[ Image.asset("assets/appimages/" + gambar),
Diperluas( anak: Kontainer( padding: EdgeInsets.all(5), anak:
Kolom( mainAxisAlignment: MainAxisAlignment.spaceEvenly ,
anak-anak: <Widget>[ Text(ini.nama, gaya: TextStyle(fontWeight:

FontWeight.bold)),
Teks(ini.deskripsi),
Teks("Harga: " + ini.harga.toString()), ], )))

])));
}
}

• Buat widget baru, MyAnimatedWidget untuk melakukan animasi fade sederhana menggunakan opacity.

kelas MyAnimatedWidget extends StatelessWidget


{ MyAnimatedWidget({this.child, this.animation});

anak Widget terakhir;


Animasi akhir<double> animasi;

Pembuatan widget(konteks BuildContext) => Pusat( anak:


AnimatedBuilder(
animasi: animasi,
pembangun: (konteks, anak) => Wadah( anak:
Opasitas(opasitas: animasi.nilai, anak: anak), ), anak: anak),

);
}

• Di sini, kami telah menggunakan AniatedBuilder untuk melakukan animasi kami. AnimatedBuilder
adalah widget yang membangun kontennya sambil melakukan animasi pada saat yang bersamaan.
Itu menerima objek animasi untuk mendapatkan nilai animasi saat ini. Kami telah menggunakan animasi

86
Machine Translated by Google

Berdebar

value, animation.value untuk mengatur opacity widget anak. Efeknya, widget akan menganimasikan
widget anak menggunakan konsep opacity.

• Terakhir, buat widget MyHomePage dan gunakan objek animasi untuk menganimasikan kontennya.

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title, this.animation}) : super(key: key);

judul String terakhir;


Animasi akhir<double> animasi;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Listing")), body: ListView( shrinkWrap: true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , anak-anak:
<Widget>[ FadeTransition(anak: ProductBox( nama: "iPhone",
deskripsi: "iPhone adalah ponsel stylist yang pernah ada", harga: 1000,
gambar: "iphone.png"), opacity: animasi), MyAnimatedWidget( anak:
ProductBox( nama: "Pixel", deskripsi: "Pixel adalah ponsel paling berfitur
yang pernah ada", harga: 800, gambar: "pixel.png"),

animasi: animasi),
ProductBox( nama: "Laptop",
deskripsi: "Laptop
adalah alat pengembangan paling produktif", harga: 2000, gambar: "laptop.png"),
ProductBox( nama: "Tablet", deskripsi: "Tablet adalah perangkat paling berguna
yang pernah ada

pertemuan",
harga: 1500,
gambar: "tablet.png"),
ProductBox( nama: "Flashdisk",
deskripsi: "Flashdisk adalah
media penyimpanan yang berguna", harga: 100, gambar:
"pendrive.png"), ProductBox( nama: "Floppy Drive", deskripsi:
"Floppy drive adalah penyimpanan penyelamat yang berguna

sedang",
harga: 20,
gambar: "floppy.png"),
],

87
Machine Translated by Google

Berdebar

));
}
}

Di sini, kami telah menggunakan FadeAnimation dan MyAnimationWidget untuk menganimasikan dua
item pertama dalam daftar. FadeAnimation adalah kelas animasi bawaan, yang kami gunakan untuk
menganimasikan anaknya menggunakan konsep opacity.

• Kode lengkapnya adalah sebagai berikut:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

kelas MyApp memperluas StatefulWidget {


_MyAppState createState() => _MyAppState();
}

kelas _MyAppState memperluas Status<MyApp> dengan SingleTickerProviderStateMixin {

Animasi<double> animasi;
Pengontrol AnimationController;

@override
void initState() {
super.initState();
controller = AnimationController(durasi: Durasi const(detik: 10), vsync: ini); animasi =
Tween<double>(mulai: 0.0, akhir: 1.0).animate(pengontrol); controller.maju();

// Widget ini adalah root dari aplikasi Anda. @override Widget


build(BuildContext context) { controller.forward(); kembalikan
MaterialApp( judul: 'Flutter Demo', tema:
ThemeData( primarySwatch: Colors.blue, ), beranda:
MyHomePage( judul: 'Halaman beranda demo tata letak
produk', animasi: animasi,)

);
}

@override
void buang()
{ controller.dispose();
super.buang();
}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title, this.animation}) : super(key: key);

88
Machine Translated by Google

Berdebar

judul String terakhir;


Animasi akhir<double> animasi;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar(title: Text("Product
Listing")), body: ListView( shrinkWrap: true, padding: const
EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0) , anak-anak:
<Widget>[ FadeTransition(anak: ProductBox( nama:
"iPhone", deskripsi: "iPhone adalah ponsel stylist yang pernah ada", harga:
1000, gambar: "iphone.png"), opacity: animasi), MyAnimatedWidget( anak:
ProductBox( nama: "Pixel", deskripsi: "Pixel adalah ponsel paling berfitur
yang pernah ada", harga: 800, gambar: "pixel.png"),

animasi: animasi),
ProductBox( nama: "Laptop",
deskripsi: "Laptop
adalah alat pengembangan paling produktif", harga: 2000, gambar:
"laptop.png"), ProductBox( nama: "Tablet", deskripsi: "Tablet adalah perangkat
paling berguna yang pernah ada

pertemuan",
harga: 1500,
gambar: "tablet.png"),

ProductBox( nama:
"Flashdisk", deskripsi: "Flashdisk adalah media penyimpanan
yang berguna", harga: 100, gambar: "flashdisk.png"), ProductBox(

nama: "Floppy Drive",


deskripsi: "Floppy drive adalah penyimpanan penyelamat yang berguna
sedang",
harga: 20,
gambar: "floppy.png"),

], ));
}
}

kelas ProductBox meluas StatelessWidget {


ProductBox({Key key, this.name, this.description, this.price, this.image}) :
super(key: key);

89
Machine Translated by Google

Berdebar

nama String akhir;


deskripsi String akhir; harga int
akhir; gambar String akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2), tinggi:
140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak:


<Widget>[ Image.asset("assets/appimages/" + gambar),
Diperluas( anak: Kontainer( padding: EdgeInsets.all(5), anak:
Kolom( mainAxisAlignment: MainAxisAlignment.spaceEvenly ,
anak-anak: <Widget>[ Text(ini.nama, gaya: TextStyle(fontWeight:

FontWeight.bold)),
Teks(ini.deskripsi),
Teks("Harga: " + ini.harga.toString()), ], )))

])));
}
}

kelas MyAnimatedWidget extends StatelessWidget


{ MyAnimatedWidget({this.child, this.animation});

anak Widget terakhir;


Animasi akhir<double> animasi;

Pembuatan widget(konteks BuildContext) => Pusat( anak:


AnimatedBuilder(
animasi: animasi,
pembangun: (konteks, anak) => Wadah( anak:
Opasitas(opasitas: animasi.nilai, anak: anak), ), anak: anak),

);
}

90
Machine Translated by Google

Berdebar

• Kompilasi dan jalankan aplikasi untuk melihat hasilnya. Versi awal dan akhir dari
aplikasinya adalah sebagai berikut:

91
Machine Translated by Google

Berdebar

92
Machine Translated by Google

11. Flutter – Menulis Kode Khusus Android Berdebar

Flutter menyediakan framework umum untuk mengakses fitur khusus platform. Hal ini memungkinkan
developer memperluas fungsionalitas framework Flutter menggunakan kode khusus platform.
Fungsi khusus platform seperti kamera, level baterai, browser, dll., dapat diakses dengan mudah melalui
framework.

Gagasan umum untuk mengakses kode khusus platform adalah melalui protokol perpesanan sederhana.
Kode Flutter, Klien dan kode platform serta Host terikat ke Saluran Pesan umum. Klien mengirim pesan ke
Host melalui Saluran Pesan. Host mendengarkan di Saluran Pesan, menerima pesan dan melakukan
fungsionalitas yang diperlukan dan akhirnya, mengembalikan hasilnya ke Klien melalui Saluran Pesan.

Arsitektur kode khusus platform ditunjukkan dalam diagram blok yang diberikan di bawah ini:

Protokol perpesanan menggunakan codec pesan standar (kelas StandardMessageCodec) yang mendukung
serialisasi biner dari nilai-nilai seperti JSON seperti angka, string, boolean, dll., Serialisasi dan de-serialisasi
bekerja secara transparan antara klien dan host.

Mari kita menulis aplikasi sederhana untuk membuka browser menggunakan Android SDK dan memahami
cara menjalankan SDK dari aplikasi flutter.

• Buat aplikasi Flutter baru di studio Android, flutter_browser_app

• Ganti kode main.dart dengan kode di bawah ini:

import 'package:flutter/material.dart';

batal main() => runApp(MyApp());

kelas MyApp extends StatelessWidget { @override

Pembuatan widget (konteks BuildContext) {


kembalikan
MaterialApp( judul: 'Flutter
Demo', tema:
ThemeData( primarySwatch:
Colors.blue, ), beranda:
MyHomePage(judul: 'Halaman Beranda Demo Flutter'),

93
Machine Translated by Google

Berdebar

);
}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
RaisedButton( child: Text('Open
Browser'), onPressed: null, ) , ), );

}
}

• Di sini, kami telah membuat tombol baru untuk membuka browser dan menetapkan metode
onPressed sebagai null.

• Sekarang, impor paket-paket berikut:

import 'dart:async';
import 'package:flutter/services.dart';

• Di sini, services.dart menyertakan fungsionalitas untuk menjalankan kode khusus platform.

• Buat saluran pesan baru di widget MyHomePage.

platform const statis = const


MethodChannel('flutterapp.tutorialspoint.com/browser');

• Tulis metode, _openBrowser untuk memanggil metode khusus platform, metode openBrowser melalui
saluran pesan.

Masa depan<void> _openBrowser() async


{ coba { final int result = menunggu
platform.invokeMethod('openBrowser',
<String, String>{ 'url':
"https://flutter.dev" });

} pada tangkapan PlatformException (e) {


// Tidak dapat membuka browser
print(e);
}
}

94
Machine Translated by Google

Berdebar

Di sini, kami telah menggunakan platform.invokeMethod untuk memanggil openBrowser (dijelaskan di langkah
selanjutnya). openBrowser memiliki argumen, url untuk membuka url tertentu.

• Ubah nilai properti onPressed dari RaisedButton dari null menjadi _openBrowser.

onPressed: _openBrowser,

• Buka MainActivity.java (di dalam folder android) dan impor pustaka yang diperlukan:

import android.app.Activity; import


android.content.Intent; impor
android.net.Uri; impor android.os.Bundle;

impor io.flutter.app.FlutterActivity; impor


io.flutter.plugin.common.MethodCall; impor
io.flutter.plugin.common.MethodChannel; impor
io.flutter.plugin.common.MethodChannel.MethodCallHandler; impor
io.flutter.plugin.common.MethodChannel.Result; impor
io.flutter.plugins.GeneratedPluginRegistrant;

• Tulis metode, openBrowser untuk membuka browser

private void openBrowser(MethodCall call, Result result, String url) {Aktivitas aktivitas = ini;
if (aktivitas == null) { result.error("ACTIVITY_NOT_AVAILABLE", "Browser tidak dapat
dibuka

tanpa aktivitas latar depan", null); return;

Maksud niat = Maksud baru (Intent.ACTION_VIEW);


maksud.setData(Uri.parse(url));

aktivitas.startActivity(niat);
hasil.sukses((Objek) benar);
}

• Sekarang, atur nama saluran di kelas MainActivity:

String CHANNEL akhir statis pribadi =


"flutterapp.tutorialspoint.com/browser";

• Tulis kode khusus android untuk mengatur penanganan pesan dalam metode onCreate.

MethodChannel baru(getFlutterView(), CHANNEL).setMethodCallHandler( new


MethodCallHandler() { @Override public void onMethodCall(Panggilan MethodCall,
Hasil hasil) {

String url = call.argument("url");

if (call.method.equals("openBrowser")) {

95
Machine Translated by Google

Berdebar

openBrowser(panggilan, hasil, url); }


else { result.notImplemented();

}
});

Di sini, kami telah membuat saluran pesan menggunakan kelas MethodChannel dan menggunakan kelas
MethodCallHandler untuk menangani pesan. onMethodCall adalah metode aktual yang bertanggung jawab
untuk memanggil kode spesifik platform yang benar dengan memeriksa pesan. metode onMethodCall
mengekstrak url dari pesan dan kemudian memanggil openBrowser hanya ketika panggilan metode adalah
openBrowser. Jika tidak, ia mengembalikan metode notImplemented.

Kode sumber lengkap aplikasi adalah sebagai berikut:

main.dart

MainActivity.java

paket com.tutorialspoint.flutterapp.flutter_browser_app;

import android.app.Activity; import


android.content.Intent; impor
android.net.Uri; impor android.os.Bundle;

impor io.flutter.app.FlutterActivity; impor


io.flutter.plugin.common.MethodCall; impor
io.flutter.plugin.common.MethodChannel.Result; impor
io.flutter.plugins.GeneratedPluginRegistrant;

kelas publik MainActivity memperluas FlutterActivity { private static


final String CHANNEL = "flutterapp.tutorialspoint.com/browser";

@Override
protected void onCreate(Bundle storedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(ini);

MethodChannel baru(getFlutterView(), CHANNEL).setMethodCallHandler( new


MethodCallHandler() { @Override public void onMethodCall(Panggilan
MethodCall, Hasil hasil) {

String url = call.argument("url");

if (call.method.equals("openBrowser"))
{ openBrowser(call, result, url); } else
{ result.notImplemented();

96
Machine Translated by Google

Berdebar

});
}

private void openBrowser (panggilan MethodCall, hasil Hasil, Url string) {


Aktivitas aktivitas = ini; if (aktivitas
== null)
{ result.error("ACTIVITY_NOT_AVAILABLE", "Browser tidak dapat dibuka
tanpa aktivitas latar depan", null); return;

Maksud niat = Maksud baru (Intent.ACTION_VIEW);


maksud.setData(Uri.parse(url));

aktivitas.startActivity(niat);
hasil.sukses((Objek) benar);
}
}

main.dart

import 'package:flutter/material.dart';

import 'dart:async'; import


'package:flutter/services.dart';

batal main() => runApp(MyApp());

kelas MyApp extends StatelessWidget { @override

Pembuatan widget (konteks BuildContext) {


return MaterialApp( title:
'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Flutter Demo
Home Page'), );

}
}

kelas MyHomePage memperluas StatelessWidget {


MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

platform const statis = const


MethodChannel('flutterapp.tutorialspoint.com/browser'); Masa
depan<void> _openBrowser() async {
coba
{ final int result = await platform.invokeMethod('openBrowser',
<String, String>{ 'url':
"https://flutter.dev" });

97
Machine Translated by Google

Berdebar

} pada tangkapan PlatformException (e) {


// Tidak dapat membuka browser
print(e);
}
}

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
RaisedButton( child: Text('Open
Browser'), onPressed: _openBrowser, ) , ), );

}
}

Jalankan aplikasi dan klik tombol Buka Browser dan Anda dapat melihat bahwa browser diluncurkan.
Aplikasi Browser - Beranda seperti yang ditunjukkan pada tangkapan layar di sini:

98
Machine Translated by Google

Berdebar

99
Machine Translated by Google

Berdebar
12. Flutter – Menulis Kode Khusus iOS

Mengakses kode khusus iOS mirip dengan yang ada di platform Android kecuali menggunakan bahasa khusus
iOS - Objective-C atau Swift dan iOS SDK. Kalau tidak, konsepnya sama dengan platform Android.

Mari kita menulis aplikasi yang sama seperti pada bab sebelumnya untuk platform iOS juga.
• Mari kita buat aplikasi baru di Android Studio (macOS), flutter_browser_ios_app

• Ikuti langkah 2 - 6 seperti pada bab sebelumnya.

• Mulai XCode dan klik File -> Buka

• Pilih proyek xcode di bawah direktori ios dari proyek flutter kami.

• Buka AppDelegate.m di bawah Runner -> Runner path. Ini berisi berikut ini
kode:

#termasuk "AppDelegate.h"
#termasuk "GeneratedPluginRegistrant.h"

@implementasi AppDelegate

- (BOOL)aplikasi:(aplikasi UIA *)aplikasi


didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//

[GeneratedPluginRegistrant registerWithRegistry:self]; // Override point


untuk kustomisasi setelah peluncuran aplikasi. kembalikan [aplikasi super:aplikasi
didFinishLaunchingWithOptions:launchOptions]; }

@akhir

• Kami telah menambahkan metode, openBrowser untuk membuka browser dengan url tertentu. Dia
menerima argumen tunggal, url.

- (kosongkan)bukaBrowser:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
UIApplication *application = [UIApplication sharedApplication];

[aplikasi openURL:url];
}

• Dalam metode didFinishLaunchingWithOptions, temukan pengontrol dan atur dalam variabel pengontrol.

100
Machine Translated by Google

Berdebar

Pengontrol FlutterViewController* =
(FlutterViewController*)self.window.rootViewController;

• Dalam metode didFinishLaunchingWithOptions, atur saluran browser sebagai


flutterapp.tutorialspoint.com/browse:

FlutterMethodChannel* browserChannel = [FlutterMethodChannel

methodChannelWithName:@"flutterapp.tutorialspoint.com/browser"
binaryMessenger:pengontrol];

• Buat variabel, weakSelf dan atur kelas saat ini:

__tipe lemah(diri) diri lemah = diri;

• Sekarang, implementasikan setMethodCallHandler. Panggil openBrowser dengan mencocokkan call.method.


Dapatkan url dengan memanggil call.arguments dan berikan sambil memanggil openBrowser.

[browserChannel setMethodCallHandler:^(panggilan FlutterMethodCall*, hasil


FlutterResult) { if ([@"openBrowser" isEqualToString:call.method]) { NSString *url =
call.arguments[@"url"];

[WeakSelf openBrowser: url]; } else


{ result(FlutterMethodNotImplemented);

}
}];

• Kode lengkapnya adalah sebagai berikut:

#termasuk "AppDelegate.h"
#termasuk "GeneratedPluginRegistrant.h"

@implementasi AppDelegate

- (BOOL)aplikasi:(aplikasi UIA *)aplikasi


didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// kode khusus dimulai


Pengontrol FlutterViewController* =

(FlutterViewController*)self.window.rootViewController;

FlutterMethodChannel* browserChannel = [FlutterMethodChannel

methodChannelWithName:@"flutterapp.tutorialspoint.com/browser"
binaryMessenger:pengontrol];

__tipe lemah(diri) diri lemah = diri;


[browserChannel setMethodCallHandler:^(FlutterMethodCall* panggilan,
Hasil FlutterResult) {
if ([@"openBrowser" isEqualToString:call.method]) { NSString *url =
call.arguments[@"url"];

101
Machine Translated by Google

Berdebar

[WeakSelf openBrowser: url]; }


else { result(FlutterMethodNotImplemented);

}
}];

// kode khusus berakhir

[GeneratedPluginRegistrant registerWithRegistry:self]; // Override


point untuk kustomisasi setelah peluncuran aplikasi. kembalikan [aplikasi
super:aplikasi didFinishLaunchingWithOptions:launchOptions]; }

- (kosongkan)bukaBrowser:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
UIApplication *application = [UIApplication sharedApplication];

[aplikasi openURL:url];
}

@akhir

• Buka pengaturan proyek.

• Buka Kemampuan dan aktifkan Mode Latar Belakang

• Tambahkan *Pengambilan latar belakang dan Notifikasi Jarak Jauh**

• Sekarang, jalankan aplikasi. Ini berfungsi mirip dengan versi Android tetapi browser Safari akan dibuka,
bukan chrome.

102
Machine Translated by Google

13. Flutter – Pengantar Paket Berdebar

Cara Dart mengatur dan berbagi serangkaian fungsi adalah melalui Paket. Paket Dart hanyalah pustaka
atau modul yang dapat dibagikan. Secara umum Paket Dart sama dengan Aplikasi Dart hanya saja Paket
Dart tidak memiliki titik masuk aplikasi, utama.

Struktur umum Paket (pertimbangkan paket demo, my_demo_package) adalah sebagai berikut:

• lib/src/* : File kode Dart Pribadi.

• lib/my_demo_package.dart: File kode Dart utama. Itu dapat diimpor ke aplikasi sebagai:

impor 'paket: my_demo_package/my_demo_package.dart'

• File kode pribadi lainnya dapat diekspor ke file kode utama


(my_demo_package.dart), jika perlu seperti yang ditunjukkan di bawah ini:

ekspor src/my_private_code.dart

• lib/* : Sejumlah file kode Dart yang diatur dalam struktur folder kustom apa pun. Kode dapat diakses
sebagai,

impor 'paket: my_demo_package/custom_folder/custom_file.dart'

• pubspec.yaml: Spesifikasi proyek, sama seperti aplikasi.

Semua file kode Dart dalam Paket hanyalah kelas Dart dan tidak memiliki persyaratan khusus untuk kode
Dart untuk memasukkannya ke dalam Paket.

Jenis Paket
Karena Paket Dart pada dasarnya adalah kumpulan kecil dari fungsi serupa, itu dapat dikategorikan
berdasarkan fungsinya.

Paket Dart
Kode Dart generik, yang dapat digunakan di lingkungan web dan seluler. Misalnya, english_words adalah
salah satu paket yang berisi sekitar 5000 kata dan memiliki fungsi utilitas dasar seperti kata benda (daftar
kata benda dalam bahasa Inggris), suku kata (sebutkan jumlah suku kata dalam sebuah kata.

Paket Flutter
Kode Dart umum, yang bergantung pada framework Flutter dan hanya dapat digunakan di lingkungan seluler.
Misalnya, fluro adalah router khusus untuk flutter. Itu tergantung pada kerangka kerja Flutter.

103
Machine Translated by Google

Berdebar

Plugin Bergetar
Kode Dart generik, yang bergantung pada framework Flutter serta kode platform yang mendasarinya (SDK Android atau SDK
iOS). Misalnya, kamera adalah plugin untuk berinteraksi dengan kamera perangkat. Itu tergantung pada framework Flutter
serta framework yang mendasarinya untuk mendapatkan akses ke kamera.

Menggunakan Paket Dart


Paket Dart dihosting dan dipublikasikan ke server langsung, https://pub.dartlang.org.
Selain itu, Flutter menyediakan alat sederhana, pub untuk mengelola Paket Dart di aplikasi. Langkah-langkah yang diperlukan
untuk menggunakan sebagai Package adalah sebagai berikut:

• Sertakan nama paket dan versi yang dibutuhkan ke dalam pubspec.yaml seperti yang ditunjukkan
di bawah:

dependensi:
english_words: ^3.1.5

• Nomor versi terbaru dapat ditemukan dengan memeriksa server online.

• Instal paket ke dalam aplikasi dengan menggunakan perintah berikut:

paket bergetar dapatkan

• Saat mengembangkan di studio Android, Android Studio mendeteksi setiap perubahan di pubspec.yaml dan
menampilkan peringatan paket Android studio kepada pengembang seperti yang ditunjukkan di bawah ini:

• Paket Dart dapat diinstal atau diperbarui di Android Studio menggunakan opsi menu.

• Impor file yang diperlukan menggunakan perintah yang ditunjukkan di bawah ini dan mulai bekerja:

import 'package:english_words/english_words.dart';

• Gunakan metode apapun yang tersedia dalam paket,

kata benda.ambil(50).untukMasing-masing(cetak);

• Di sini, kami telah menggunakan fungsi kata benda untuk mendapatkan dan mencetak 50 kata teratas.

Kembangkan Paket Plugin Flutter


Mengembangkan Plugin Flutter mirip dengan mengembangkan aplikasi Dart atau Paket Dart. Satu-satunya pengecualian
adalah plugin akan menggunakan API Sistem (Android atau iOS) untuk mendapatkan fungsionalitas khusus platform yang
diperlukan.

Seperti yang telah kita pelajari cara mengakses kode platform di bab sebelumnya, mari kita kembangkan sebuah plugin
sederhana, my_browser untuk memahami proses pengembangan plugin. Itu

104
Machine Translated by Google

Berdebar

fungsionalitas plugin my_browser adalah untuk memungkinkan aplikasi membuka situs web yang diberikan di
browser khusus platform.

• Mulai Android Studio

• Klik File -> New Flutter Project dan pilih opsi Flutter Plugin.

• Anda dapat melihat jendela pemilihan plugin Flutter seperti yang ditunjukkan di sini:

• Masukkan my_browser sebagai nama proyek dan klik Berikutnya.

105
Machine Translated by Google

Berdebar

• Masukkan nama plugin dan detail lainnya di jendela seperti yang ditunjukkan di sini:

• Masukkan domain perusahaan, flutterplugins.tutorialspoint.com di jendela yang ditunjukkan di bawah


ini, lalu klik Selesai. Ini akan menghasilkan kode startup untuk mengembangkan plugin baru kami.

106
Machine Translated by Google

Berdebar

• Buka file my_browser.dart dan tulis metode, openBrowser untuk memanggil platform
metode openBrowser tertentu.

Future<void> openBrowser(String urlString) async {


coba
{ final int result = menunggu _channel.invokeMethod('openBrowser', <String,
String>{
'url': urlString });

} pada tangkapan PlatformException (e) {


// Tidak dapat membuka browser
print(e);
}
}

• Buka file MyBrowserPlugin.java dan impor kelas-kelas berikut:

import android.app.Activity; import


android.content.Intent; impor
android.net.Uri; impor android.os.Bundle;

• Di sini, kita harus mengimpor library yang diperlukan untuk membuka browser dari Android.

• Tambahkan mRegistrar variabel pribadi baru dari tipe Registrar di kelas MyBrowserPlugin.

mRegistrar Registrar akhir pribadi;

• Di sini, Registrar digunakan untuk mendapatkan informasi konteks dari kode pemanggilan.

• Tambahkan konstruktor untuk mengatur Registrar di kelas MyBrowserPlugin.

private MyBrowserPlugin(Registrar registrar) { this.mRegistrar


= registrar; }

• Ubah registerWith untuk menyertakan konstruktor baru kita di kelas MyBrowserPlugin.

public static void registerWith(Registrar registrar) { final MethodChannel


channel = new MethodChannel(registrar.messenger(),
"my_browser");
Contoh MyBrowserPlugin = new MyBrowserPlugin(registrar);
channel.setMethodCallHandler(instance);
}

• Ubah onMethodCall untuk menyertakan metode openBrowser di kelas MyBrowserPlugin.

@Override
public void onMethodCall(Panggilan MethodCall, Hasil hasil) {

String url = call.argument("url");

107
Machine Translated by Google

Berdebar

if (call.method.equals("getPlatformVersion"))
{ result.success("Android " + android.os.Build.VERSION.RELEASE); } else if
(call.method.equals("openBrowser")) {
openBrowser(panggilan, hasil, url); }
else { result.notImplemented();

}
}

• Tulis metode openBrowser khusus platform untuk mengakses browser


Kelas MyBrowserPlugin:

private void openBrowser (panggilan MethodCall, hasil Hasil, Url string) {


Aktivitas aktivitas = mRegistrar.aktivitas(); if (aktivitas
== null) { result.error("ACTIVITY_NOT_AVAILABLE",
"Browser tidak dapat dibuka tanpa aktivitas latar depan", null); kembali;

Maksud niat = Maksud baru (Intent.ACTION_VIEW);


maksud.setData(Uri.parse(url));

aktivitas.startActivity(niat);
hasil.sukses((Objek) benar);
}

• Kode sumber lengkap plugin my_browser adalah sebagai berikut:

my_browser.dart

import 'dart:async';

import 'package:flutter/services.dart';

kelas Peramban Saya {


static const MethodChannel _channel = const
MethodChannel('my_browser');

masa depan statis<String> dapatkan platformVersion async {


versi String akhir = menunggu
_channel.invokeMethod('getPlatformVersion'); versi
pengembalian;
}

Future<void> openBrowser(String urlString) async {


coba
{ final int result = menunggu _channel.invokeMethod('openBrowser',
<String, String>{ 'url':
urlString });

} pada tangkapan PlatformException (e) {


// Tidak dapat membuka browser
print(e);
}

108
Machine Translated by Google

Berdebar

}
}

MyBrowserPlugin.java

paket com.tutorialspoint.flutterplugins.my_browser;

impor io.flutter.plugin.common.MethodCall; impor


io.flutter.plugin.common.MethodChannel; impor
io.flutter.plugin.common.MethodChannel.MethodCallHandler; impor
io.flutter.plugin.common.MethodChannel.Result; impor
io.flutter.plugin.common.PluginRegistry.Registrar;

import android.app.Activity; import


android.content.Intent; impor
android.net.Uri; impor android.os.Bundle;

/** MyBrowserPlugin */ kelas


publik MyBrowserPlugin mengimplementasikan MethodCallHandler {
mRegistrar Registrar akhir pribadi;

private MyBrowserPlugin(Registrar registrar) { this.mRegistrar


= registrar;
}

/** Pendaftaran plugin. */ public


static void registerWith(Registrar registrar) { final MethodChannel
channel = new MethodChannel(registrar.messenger(), "my_browser"); Contoh
MyBrowserPlugin = new MyBrowserPlugin(registrar); channel.setMethodCallHandler(instance);

@Override
public void onMethodCall(Panggilan MethodCall, Hasil hasil) {
String url = call.argument("url");

if (call.method.equals("getPlatformVersion"))
{ result.success("Android " + android.os.Build.VERSION.RELEASE); } else if
(call.method.equals("openBrowser")) {
openBrowser(panggilan, hasil, url); }
else { result.notImplemented();

}
}

private void openBrowser (panggilan MethodCall, hasil Hasil, Url string) {


Aktivitas aktivitas = mRegistrar.aktivitas(); if (aktivitas
== null) {
result.error("ACTIVITY_NOT_AVAILABLE", "Browser tidak dapat dibuka
tanpa aktivitas latar depan", null); return;

109
Machine Translated by Google

Berdebar

Maksud niat = Maksud baru (Intent.ACTION_VIEW);


maksud.setData(Uri.parse(url));

aktivitas.startActivity(niat);
hasil.sukses((Objek) benar);
}
}

• Buat proyek baru, my_browser_plugin_test untuk menguji plugin kita yang baru dibuat.

• Buka pubspec.yaml dan atur my_browser sebagai dependensi plugin:

dependensi:
bergetar:
sdk: bergetar

my_browser:
jalur: ../my_browser

• Android studio akan memberi tahu bahwa pubspec.yaml diperbarui seperti yang ditunjukkan dalam peringatan
paket Android studio yang diberikan di bawah ini:

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan
mengonfigurasinya dengan benar untuk aplikasi tersebut.

• Buka main.dart dan sertakan plugin my_browser seperti di bawah ini:

import 'package:my_browser/my_browser.dart';

• Panggil fungsi openBrowser dari plugin my_browser seperti yang ditunjukkan di bawah ini:

onPressed: () => MyBrowser().openBrowser("https://flutter.dev"),

• Kode lengkap dari main.dart adalah sebagai berikut:

import 'package:flutter/material.dart'; import


'package:my_browser/my_browser.dart';

batal main() => runApp(MyApp());

kelas MyApp extends StatelessWidget { @override

Pembuatan widget (konteks BuildContext) {


return MaterialApp( title:
'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage(title: 'Flutter Demo
Home Page'), );

110
Machine Translated by Google

Berdebar

}
}

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title:
Text(this.title), ), body: Center( child:
RaisedButton( child: Text('Buka
Browser'), onPressed: () = >
MyBrowser().openBrowser("https://
flutter.dev"), ), ), );

}
}

111
Machine Translated by Google

Berdebar

• Jalankan aplikasi dan klik tombol Buka Browser dan lihat bahwa browser diluncurkan. Anda dapat melihat aplikasi Browser
- Beranda seperti yang ditunjukkan pada tangkapan layar yang ditunjukkan di bawah ini:

112
Machine Translated by Google

Berdebar

• Anda dapat melihat aplikasi Browser – Layar browser seperti yang ditunjukkan pada tangkapan layar yang ditampilkan
di bawah:

113
Machine Translated by Google

Berdebar
14. Flutter – Mengakses REST API

Flutter menyediakan paket http untuk menggunakan sumber daya HTTP. http adalah pustaka berbasis masa depan dan
menggunakan fitur await dan async. Ini menyediakan banyak metode tingkat tinggi dan menyederhanakan pengembangan
aplikasi seluler berbasis REST.

Konsep dasar
Paket http menyediakan kelas tingkat tinggi dan http untuk melakukan permintaan web.

• Kelas http menyediakan fungsionalitas untuk melakukan semua jenis permintaan HTTP.

• Metode http menerima url, dan informasi tambahan melalui Dart Map (data posting, header tambahan, dll.,). Itu
meminta server dan mengumpulkan respons kembali dalam pola async/menunggu. Misalnya, kode di bawah ini
membaca data dari url yang ditentukan dan mencetaknya di konsol.

print(menunggu http.read('https://flutter.dev/'));

Beberapa metode inti adalah sebagai berikut:

• baca - Minta url yang ditentukan melalui metode GET dan kembalikan respons sebagai Future<String>

• get - Minta url yang ditentukan melalui metode GET dan kembalikan respons sebagai Future<Response>. Response
adalah kelas yang menyimpan informasi respon.

• post - Meminta url yang ditentukan melalui metode POST dengan memposting data yang disediakan dan
mengembalikan respons sebagai Future<Response>

• put - Minta url yang ditentukan melalui metode PUT dan kembalikan responsnya
sebagai Masa Depan<Respon>

• head - Minta url yang ditentukan melalui metode HEAD dan kembalikan
respon sebagai Future<Response>

• hapus - Minta url yang ditentukan melalui metode DELETE dan kembalikan
respon sebagai Future<Response>

http juga menyediakan kelas klien HTTP yang lebih standar, klien. klien mendukung koneksi persisten. Ini akan berguna
bila banyak permintaan yang akan dilakukan ke server tertentu. Itu harus ditutup dengan benar menggunakan metode
tutup. Kalau tidak, ini mirip dengan kelas http. Contoh kodenya adalah sebagai berikut:

var client = new http.Client(); coba


{ print(menunggu client.get('https://
flutter.dev/')); } akhirnya { client.close();

114
Machine Translated by Google

Berdebar

Mengakses ProductserviceAPI
Mari kita buat aplikasi sederhana untuk mendapatkan data produk dari server web dan kemudian menampilkan
produk menggunakan ListView.

• Buat aplikasi Flutter baru di studio Android, product_rest_app

• Ganti kode startup default (main.dart) dengan kode product_nav_app kami .

• Salin folder aset dari product_nav_app ke product_rest_app dan tambahkan aset


di dalam file pubspec.yaml

berdebar:

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/
pendrive.png - aset/appimages/pixel.png -
aset/appimages/tablet.png

• Konfigurasikan paket http pada file pubspec.yaml seperti gambar di bawah ini:

dependensi: http:
^0.12.0+2

• Di sini, kita akan menggunakan paket http versi terbaru. Studio Android akan mengirimkan peringatan paket
bahwa pubspec.yaml telah diperbarui.

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan mengonfigurasinya
dengan benar untuk aplikasi tersebut.

• Impor paket http di file main.dart:

import 'dart:async'; impor


'panah: konversi'; impor
'paket:http/http.dart' sebagai http;

• Buat file JSON baru, products.json dengan informasi produk seperti yang ditunjukkan di bawah ini:

[
{
"name": "iPhone",
"description": "iPhone adalah ponsel stylist yang pernah ada", "price":
1000, "image": "iphone.png"

},
{
"name": "Pixel",
"description": "Pixel adalah ponsel berfitur paling banyak", "price": 800,
"image": "pixel.png"

115
Machine Translated by Google

Berdebar

},
{
"name": "Laptop",
"description": "Laptop adalah alat pengembangan paling produktif", "price": 2000,
"image": "laptop.png"

},
{
"name": "Tablet",
"description": "Tablet adalah perangkat yang paling berguna untuk rapat", "price": 1500,
"image": "tablet.png"

},
{
"name": "Flashdisk",
"description": "Flashdisk adalah media penyimpanan yang berguna",
"price": 100, "image": "flashdisk.png"

},
{
"name": "Floppy Drive",
"description": "Floppy drive adalah media penyimpanan penyelamat yang berguna",
"price": 20, "image": "floppy.png"

}
]

• Buat folder baru, JSONWebServer dan tempatkan file JSON, products.json.

• Jalankan server web apa pun dengan JSONWebServer sebagai direktori akarnya dan dapatkan jalur webnya.
Misalnya, http://192.168.184.1:8000/products.json. Kita dapat menggunakan server web apa saja seperti
apache, nginx dll.,

• Cara termudah adalah menginstal aplikasi http-server berbasis node. Ikuti langkah-langkah yang diberikan
di bawah ini untuk menginstal dan menjalankan aplikasi server http.

• Instal aplikasi Nodejs (https://nodejs.org/en/)


• Buka folder JSONWebServer.

cd /jalur/ke/JSONWebServer

• Instal paket http-server menggunakan npm

npm install -g http-server

• Sekarang, jalankan server.

http-server . -p 8000

Memulai http-server, melayani .


Tersedia di:
http://192.168.99.1:8000 http://
192.168.1.2:8000

116
Machine Translated by Google

Berdebar

http://127.0.0.1:8000 Tekan
CTRL-C untuk menghentikan server

• Buat file baru, Product.dart di folder lib dan pindahkan kelas Produk ke dalamnya.

• Tulis konstruktor pabrik di kelas Produk, Product.fromMap untuk mengonversi Peta data yang
dipetakan menjadi objek Produk. Biasanya, file JSON akan diubah menjadi objek Dart Map dan
kemudian diubah menjadi objek yang relevan (Produk)

pabrik Product.fromJson(Map<String, dynamic> data) {


return

Produk( data['nama'],
data['deskripsi'],
data['harga'],
data['gambar'], );
}

• Kode lengkap dari Product.dart adalah sebagai berikut:

kelas Produk
{ nama String akhir;
deskripsi String akhir; harga int
akhir; gambar String akhir;

Produk(ini.nama, ini.deskripsi, ini.harga, ini.gambar);

pabrik Product.fromMap(Map<String, dynamic> json) { return


Product( json['nama'], json['deskripsi'], json['harga'], json['gambar'], );

}
}

• Tulis dua metode - parseProducts dan fetchProducts - di kelas utama untuk mengambil dan memuat
informasi produk dari server web ke dalam objek List<Product> .

List<Product> parseProducts(String responseBody) { final parsing


= json.decode(responseBody).cast<Map<String, dynamic>>(); return
parsed.map<Product>((json) => Product.fromJson(json)).toList();
}

Future<Daftar<Produk>> fetchProducts() async {


tanggapan akhir = menunggu
http.get('http://192.168.1.2:8000/products.json');

if (response.statusCode == 200) {
return parseProducts(response.body); } else
{ throw Exception('Tidak dapat mengambil produk
dari REST API');

117
Machine Translated by Google

Berdebar

}
}

• Perhatikan poin-poin berikut di sini:

• Future digunakan untuk memuat informasi produk dengan malas. Pemuatan malas adalah konsep
untuk menunda eksekusi kode sampai diperlukan.

• http.get digunakan untuk mengambil data dari Internet.

• json.decode digunakan untuk mendekode data JSON ke dalam objek Dart Map. Setelah data JSON
didekodekan, data tersebut akan diubah menjadi List<Product> menggunakan fromMap dari kelas
Produk.

• Di kelas MyApp, tambahkan variabel anggota baru, produk bertipe Future<Product> dan sertakan
dalam konstruktor.

kelas MyApp memperluas StatelessWidget {


produk masa depan<Daftar<Produk>> akhir;

MyApp({Key key, this.products}) : super(key: key);

...

• Di kelas MyHomePage, tambahkan produk variabel anggota baru dengan tipe Future<Product> dan
sertakan dalam konstruktor. Juga, hapus variabel item dan metode yang relevan, panggilan metode
getProducts. Menempatkan variabel produk dalam konstruktor. Ini akan memungkinkan untuk
mengambil produk dari Internet hanya sekali saat aplikasi pertama kali dijalankan.

kelas MyHomePage extends StatelessWidget { final


String title; produk masa depan<Daftar<Produk>>
akhir;

MyHomePage({Key key, this.title, this.products}) : super(key: key);


...

• Ubah opsi beranda (MyHomePage) dalam metode build widget MyApp menjadi
mengakomodasi perubahan di atas:

rumah: MyHomePage
(judul: 'halaman muka demo Navigasi Produk', produk: produk),

• Ubah fungsi utama untuk menyertakan argumen Future<Product>:

void main() => runApp(MyApp(fetchProduct()));

• Buat widget baru, ProductBoxList untuk membuat daftar produk di halaman beranda.

kelas ProductBoxList memperluas StatelessWidget {


item Daftar<Produk> akhir;

118
Machine Translated by Google

Berdebar

ProductBoxList({Key key, this.items});

@override
Widget build(Konteks BuildContext) { return
ListView.builder(
itemCount: items.length,
itemBuilder: (konteks, indeks) { return
GestureDetector( anak: ProductBox(item:
item[indeks]), onTap: () { Navigator.push( konteks,
MaterialPageRoute(

pembangun: (konteks) => ProductPage(item: item[indeks]), ), ); }, ); }, );

}
}

Perhatikan bahwa kami menggunakan konsep yang sama yang digunakan dalam aplikasi Navigasi untuk
mencantumkan produk kecuali itu dirancang sebagai widget terpisah dengan mengirimkan produk (objek)
bertipe List<Product>.

• Terakhir, modifikasi metode build widget MyHomePage untuk mendapatkan informasi


produk menggunakan opsi Future, bukan panggilan metode normal.

Pembuatan widget (konteks BuildContext) {


return Scaffold( appBar:
AppBar(judul: Teks("Navigasi Produk")), body: Center(

anak: FutureBuilder<Daftar<Produk>>( masa


depan: produk, pembangun: (konteks,
snapshot) {
if (snapshot.hasError) print(snapshot.error);

mengembalikan
snapshot.hasData ?
ProductBoxList( item: snapshot.data) // kembalikan widget ListView
: Pusat(anak: CircularProgressIndicator());

}, ), ));
}

• Di sini perhatikan bahwa kami menggunakan widget FutureBuilder untuk merender widget. FutureBuilder
akan mencoba mengambil data dari properti masa depan (tipe Future<List<Product>>).
Jika properti mendatang mengembalikan data, itu akan merender widget menggunakan ProductBoxList, jika
tidak akan menimbulkan kesalahan.

119
Machine Translated by Google

Berdebar

• Kode lengkap dari main.dart adalah sebagai berikut:

import 'package:flutter/material.dart';

import 'dart:async'; impor


'panah: konversi'; impor
'paket:http/http.dart' sebagai http;

impor 'Produk.dart';

void main() => runApp(MyApp(produk: fetchProducts()));

List<Product> parseProducts(String responseBody) { final parsing


= json.decode(responseBody).cast<Map<String, dynamic>>(); return
parsed.map<Product>((json) => Product.fromMap(json)).toList();
}

Future<Daftar<Produk>> fetchProducts() async {


tanggapan akhir = menunggu
http.get('http://192.168.1.2:8000/products.json');

if (response.statusCode == 200) {
return parseProducts(response.body); } else
{ throw Exception('Tidak dapat mengambil produk
dari REST API');
}
}

kelas MyApp memperluas StatelessWidget {


produk masa depan<Daftar<Produk>> akhir;

MyApp({Key key, this.products}) : super(key: key);

// Widget ini adalah root dari aplikasi Anda. @override Widget


build(Konteks BuildContext) {

return MaterialApp( title:


'Flutter Demo', theme:
ThemeData( primarySwatch:
Colors.blue, ), home:
MyHomePage( title: 'Product
Navigation demo home page',
products: products), );

}
}

kelas MyHomePage extends StatelessWidget { final


String title; produk masa depan<Daftar<Produk>>
akhir;

MyHomePage({Key key, this.title, this.products}) : super(key: key);

// item akhir = Product.getProducts();

120
Machine Translated by Google

Berdebar

@mengesampingkan

Widget build(BuildContext context) { return


Scaffold( appBar: AppBar(title: Text("Product
Navigation")), body: Center( child:
FutureBuilder<List<Product>>( future: products, builder: (context,
snapshot) {

if (snapshot.hasError) print(snapshot.error);

mengembalikan
snapshot.hasData ?
ProductBoxList( item: snapshot.data) // kembalikan widget ListView
: Pusat(anak: CircularProgressIndicator());

}, ), ));
}
}

kelas ProductBoxList memperluas StatelessWidget {


item Daftar<Produk> akhir;

ProductBoxList({Key key, this.items});

@override
Widget build(Konteks BuildContext) { return
ListView.builder(
itemCount: items.length,
itemBuilder: (konteks, indeks) { return
GestureDetector( anak:
ProductBox(item: item[indeks]), onTap: ()
{ Navigator.push( konteks, MaterialPageRoute(

pembangun: (konteks) => ProductPage(item: item[indeks]), ), ); }, ); }, );

}
}

kelas ProductPage memperluas StatelessWidget {


ProductPage({Key key, this.item}) : super(key: key);

item Produk akhir;

@mengesampingkan

Pembuatan widget(konteks BuildContext)


{ return Scaffold(

121
Machine Translated by Google

Berdebar

appBar: AppBar( title:


Text(this.item.name), ), body:
Center( child: Container( padding:
EdgeInsets.all(0), child:
Column( mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start, anak-anak:
<Widget>[ Image.asset("assets/appimages/" +
this.item.image), Diperluas( anak: Kontainer( padding:
EdgeInsets.all(5), anak: Kolom( mainAxisAlignment:
MainAxisAlignment.spaceEvenly,

anak-anak: <Widget>[
Teks(nama.item.ini, gaya:
TextStyle(Berat font:
FontWeight.bold)),
Text(this.item.description),
Text("Harga: " + this.item.price.toString()), RatingBox(), ], )))

]),

), ), );

}
}

kelas RatingBox extends StatefulWidget { @override

_RatingBoxState createState() => _RatingBoxState();


}

kelas _RatingBoxState memperluas Status<RatingBox> {


int _peringkat = 0;

batal _setRatingAsOne()
{ setState(() { _rating = 1; });

batal _setRatingAsTwo()
{ setState(() { _rating = 2; });

batal _setRatingAsThree()
{ setState(() {

122
Machine Translated by Google

Berdebar

_peringkat =
3; });
}

Pembuatan widget (konteks BuildContext) {


ukuran_ganda = 20;
cetak(_peringkat);

kembalikan
Row( mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max, anak:
<Widget>[ Container( padding: EdgeInsets.all(0),
anak: IconButton(

ikon: (_rating >= 1 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsOne,
iconSize: _size, ), ),
Container( padding:
EdgeInsets.all(0), anak: IconButton(

ikon: (_rating >= 2 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)
:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsTwo,
iconSize: _size, ), ),
Wadah( padding: EdgeInsets.all(0),
anak: IconButton(

ikon: (_rating >= 3 ?


Ikon( Bintang ikon,
ukuran:
_ukuran,
)

123
Machine Translated by Google

Berdebar

:
Ikon( Icons.star_border,
ukuran: _ukuran, )),
warna: Warna.merah[500],
onPressed: _setRatingAsThree,
iconSize: _size, ), ), ], );

}
}

kelas ProductBox meluas StatelessWidget {


ProductBox({Key key, this.item}) : super(key: key);

item Produk akhir;

Widget build(BuildContext context) { return


Container( padding: EdgeInsets.all(2),
tinggi: 140, anak: Kartu( anak: Baris(

mainAxisAlignment: MainAxisAlignment.spaceEvenly, anak-


anak: <Widget>[ Image.asset("assets/appimages/" +
this.item.image), Diperluas( anak: Kontainer( padding:
EdgeInsets.all(5), anak: Kolom( mainAxisAlignment :
MainAxisAlignment.spaceEvenly, anak-anak: <Widget>[

Teks(nama.item.ini, gaya:
TextStyle(Berat font:
FontWeight.bold)),
Text(this.item.description),
Text("Harga: " + this.item.price.toString()), RatingBox(), ], )))

]),
));
}
}

Terakhir jalankan aplikasi untuk melihat hasilnya. Ini akan sama dengan contoh Navigasi kami kecuali
datanya berasal dari Internet dan bukan dari lokal, data statis dimasukkan saat mengkode aplikasi.

124
Machine Translated by Google

15. Flutter – Konsep Basis Data Berdebar

Flutter menyediakan banyak paket lanjutan untuk bekerja dengan database. Paket yang paling penting adalah:

• sqflite – Digunakan untuk mengakses dan memanipulasi database SQLite, dan

• firebase_database – Digunakan untuk mengakses dan memanipulasi database NoSQL yang dihosting cloud
dari Google.

Dalam bab ini, mari kita bahas masing-masing secara rinci.

SQLite
Basis data SQLite adalah mesin basis data tertanam berbasis SQL de-facto dan standar. Ini adalah mesin database
kecil dan teruji waktu. paket sqflite menyediakan banyak fungsi untuk bekerja secara efisien dengan database
SQLite. Ini menyediakan metode standar untuk memanipulasi mesin database SQLite. Fungsionalitas inti yang
disediakan oleh paket sqllite adalah sebagai berikut:

• Membuat/Buka (metode openDatabase) database SQLite.

• Jalankan pernyataan SQL (metode eksekusi) terhadap database SQLite.

• Metode kueri tingkat lanjut (metode kueri) untuk direduksi menjadi kode yang diperlukan untuk kueri dan
dapatkan informasi dari database SQLite.

Mari kita membuat aplikasi produk untuk menyimpan dan mengambil informasi produk dari mesin database SQLite
standar menggunakan paket sqlite dan memahami konsep di balik database SQLite dan paket sqlite.

• Buat aplikasi Flutter baru di studio Android, product_sqlite_app

• Ganti kode startup default (main.dart) dengan kode product_rest_app kami .

• Salin folder aset dari product_nav_app ke product_rest_app dan tambahkan aset


di dalam file *pubspec.yaml`

berdebar:

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/pendrive.png
- aset/appimages/pixel.png - aset/
appimages/tablet.png

• Konfigurasikan paket sqflite di file pubspec.yaml seperti yang ditunjukkan di bawah ini:

dependensi:
sqllite: apa saja

125
Machine Translated by Google

Berdebar

Gunakan nomor versi terbaru dari sqflite sebagai pengganti

• Konfigurasikan paket path_provider pada file pubspec.yaml seperti gambar di bawah ini:

dependensi:
path_provider: apapun

• Di sini, paket path_provider digunakan untuk mendapatkan jalur folder sementara dari sistem dan
jalur aplikasi. Gunakan nomor versi terbaru dari sqflite sebagai pengganti .

• Android studio akan memberi tahu bahwa pubspec.yaml telah diperbarui.

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan
mengonfigurasinya dengan benar untuk aplikasi tersebut.

• Dalam database, kita membutuhkan primary key, id sebagai kolom tambahan bersama dengan
properti Produk seperti nama, harga, dll. Jadi, tambahkan properti id di kelas Produk. Juga, tambahkan
metode baru, toMap untuk mengonversi objek produk menjadi objek Peta. fromMap dan toMap
digunakan untuk serialisasi dan de-serialisasi objek Produk dan digunakan dalam metode manipulasi
basis data.

kelas Produk { final


int id; nama String
akhir; deskripsi String
akhir; harga int akhir; gambar
String akhir;

kolom akhir statis = ["id", "nama", "deskripsi", "harga", "gambar"];

Produk(ini.id, ini.nama, ini.deskripsi, ini.harga, ini.gambar);

pabrik Product.fromMap(Map<String, dynamic> data) { return


Product( data['id'], data['name'], data['description'], data['price'],
data['image' ], );

Peta<String, dinamis> toMap() => { "id": id,


"nama": nama, "deskripsi": deskripsi,
"harga": harga, "gambar": gambar };

• Buat file baru, Database.dart di folder lib untuk menulis fungsionalitas terkait SQLite .

• Impor pernyataan impor yang diperlukan di Database.dart

126
Machine Translated by Google

Berdebar

import 'dart:async'; impor


'panah: io'; impor 'paket: jalur/
jalur.dart';

import 'package:path_provider/path_provider.dart'; impor 'paket: sqflite/


sqflite.dart';

impor 'Produk.dart';

• Perhatikan poin-poin berikut di sini:

• async digunakan untuk menulis metode asinkron.

• io digunakan untuk mengakses file dan direktori.

• path digunakan untuk mengakses fungsi utilitas inti dart yang terkait dengan jalur file.

• path_provider digunakan untuk mendapatkan path sementara dan aplikasi.

• sqflite digunakan untuk memanipulasi database SQLite.

• Buat kelas baru SQLiteDbProvider

• Deklarasikan objek SQLiteDbProvider statis berbasis singleton seperti yang ditentukan di bawah ini:

kelas SQLiteDbProvider
{ SQLiteDbProvider._();

statis final SQLiteDbProvider db = SQLiteDbProvider._();

database statis _database;


}

• Objek SQLiteDBProvoider dan metodenya dapat diakses melalui db statis


variabel.

SQLiteDBProvoider.db.<emthod>

• Buat metode untuk mendapatkan database (opsi Masa Depan) dengan tipe Future<Database>.
Buat tabel produk dan muat data awal selama pembuatan database itu sendiri.

Future<Database> dapatkan database async { if


(_database != null) return _database;

_database = menunggu initDB();


mengembalikan _database;
}

initDB() asinkron {
Direktori dokumenDirektori = menunggu
getApplicationDocumentsDirectory(); Jalur string =
gabung(documentsDirectory.path, "ProductDB.db"); kembali menunggu openDatabase( path,
versi: 1,

127
Machine Translated by Google

Berdebar

onOpen: (db) {},


onCreate: (Database db, versi int) async {

await db.execute("CREATE TABLE Product (" "id


INTEGER PRIMARY KEY," "name TEXT,"
"description TEXT," "price INTEGER,"
"image TEXT" ")");

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[1, "iPhone", "iPhone adalah ponsel penata gaya", 1000,
"iphone.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[2, "Pixel", "Pixel adalah ponsel berfitur terbanyak yang pernah ada", 800,
"piksel.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[3, "Laptop", "Laptop adalah alat pengembangan paling produktif",
2000, "laptop.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[4, "Tablet", "Laptop adalah alat pengembangan paling produktif",
1500, "tablet.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[5, "Flashdisk", "Flashdisk adalah media penyimpanan yang berguna",
100, "Flashdisk.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[6, "Floppy Drive", "Floppy drive adalah media penyimpanan penyelamat
yang berguna", 20, "floppy.png"]); });

• Di sini, kami telah menggunakan metode berikut:

• getApplicationDocumentsDirectory - Mengembalikan path direktori aplikasi • join -


Digunakan untuk membuat path khusus sistem. Kami telah menggunakannya untuk membuat database
jalur.

128
Machine Translated by Google

Berdebar

• openDatabase - Digunakan untuk membuka database SQLite • onOpen

- Digunakan untuk menulis kode saat membuka database

• onCreate - Digunakan untuk menulis kode saat database dibuat untuk pertama kali

• db.execute - Digunakan untuk mengeksekusi kueri SQL. Itu menerima kueri. Jika kueri memiliki

placeholder (?), lalu menerima nilai sebagai daftar di argumen kedua.

• Tulis metode untuk mendapatkan semua produk dalam database:

Masa Depan<Daftar<Produk>> getAllProducts() async { final db =


menunggu basis data;

Daftar<Peta> hasil = menunggu db.query("Produk", kolom: Produk.kolom, orderBy: "id ASC");

Daftar<Produk> produk = Daftar baru();


results.forEach((result) { Produk produk =
Produk.dariPeta(hasil); produk.tambahkan(produk); });

mengembalikan produk;
}

• Di sini, kami telah melakukan hal berikut:

• Menggunakan metode kueri untuk mengambil semua informasi produk. kueri menyediakan pintasan untuk
menanyakan informasi tabel tanpa menulis seluruh kueri. metode kueri akan menghasilkan kueri yang tepat
dengan menggunakan input kami seperti kolom, orderBy, dll.,

• Menggunakan metode fromMap Produk untuk mendapatkan detail produk dengan mengulang hasilnya
objek, yang menampung semua baris dalam tabel.

• Tulis metode untuk mendapatkan produk khusus untuk id

Future<Product> getProductById(int id) async { final db = menunggu


basis data;

var result = await db.query("Produk", di mana: "id = ", di manaArgs: [id]);

mengembalikan result.isNotEmpty ? Product.fromMap(result.first): Null;


}

• Di sini, kami telah menggunakan where dan whereArgs untuk menerapkan filter.

• Buat tiga metode - masukkan, perbarui dan hapus metode untuk memasukkan, memperbarui dan menghapus
produk dari database

masukkan (Produk produk) async { final db =


menunggu basis data;

var maxIdResult = await db.rawQuery("SELECT MAX(id)+1 as last_inserted_id FROM


Product");

129
Machine Translated by Google

Berdebar

var id = maxIdResult.first["last_inserted_id"];

var result = menunggu db.rawInsert(


"MASUKKAN Ke Dalam Produk (id, nama, deskripsi, harga, gambar)"
"
NILAI (?, ?, ?, ?, ?)",
[id, nama produk, deskripsi produk, harga produk,
gambar produk] );

mengembalikan hasil;
}

perbarui (Produk produk) async { final db =


menunggu basis data;

var result = await db.update("Product", product.toMap(), where: "id = ?", whereArgs:


[product.id]);

mengembalikan hasil;
}

hapus (int id) async { final db =


menunggu basis data;

db.delete("Produk", di mana: "id = ?", di manaArgs: [id]);


}

• Kode akhir dari Database.dart adalah sebagai berikut:

import 'dart:async';
impor 'panah: io'; impor
'paket: jalur/jalur.dart';

import 'package:path_provider/path_provider.dart'; impor 'paket: sqflite/


sqflite.dart';

impor 'Produk.dart';

kelas SQLiteDbProvider
{ SQLiteDbProvider._();

statis final SQLiteDbProvider db = SQLiteDbProvider._();

database statis _database;

Future<Database> dapatkan database async { if


(_database != null) return _database;

_database = menunggu initDB();


mengembalikan _database;
}

initDB() asinkron {

130
Machine Translated by Google

Berdebar

Direktori dokumenDirektori = menunggu


getApplicationDocumentsDirectory(); Jalur
string = gabung(documentsDirectory.path, "ProductDB.db"); kembali
menunggu openDatabase( path, versi: 1, onOpen: (db) {}, onCreate:
(Database db, versi int) async {

await db.execute("CREATE TABLE Product (" "id


INTEGER PRIMARY KEY," "name TEXT,"
"description TEXT," "price INTEGER,"
"image TEXT" ")");

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[1, "iPhone", "iPhone adalah ponsel penata gaya", 1000,
"iphone.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[2, "Pixel", "Pixel adalah ponsel berfitur terbanyak yang pernah ada", 800,
"piksel.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[3, "Laptop", "Laptop adalah alat pengembangan paling produktif",
2000, "laptop.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[4, "Tablet", "Laptop adalah alat pengembangan paling produktif",
1500, "tablet.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[5, "Flashdisk", "Flashdisk adalah media penyimpanan yang berguna",
100, "Flashdisk.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[6, "Floppy Drive", "Floppy drive adalah media penyimpanan penyelamat
yang berguna", 20, "floppy.png"]); });

131
Machine Translated by Google

Berdebar

Future<Daftar<Produk>> getAllProducts() async {


final db = menunggu basis data;

Daftar<Peta> hasil = menunggu db.query("Produk", kolom: Produk.kolom,


orderBy: "id ASC");

Daftar<Produk> produk = Daftar baru();


results.forEach((result) { Produk produk =
Produk.dariPeta(hasil); produk.tambahkan(produk); });

mengembalikan produk;
}

Future<Product> getProductById(int id) async {


final db = menunggu basis data;

var result = await db.query("Produk", di mana: "id = ", di manaArgs: [id]);

mengembalikan result.isNotEmpty ? Product.fromMap(result.first): Null;


}

masukkan (Produk produk) async { final


db = menunggu basis data;

var maxIdResult = await db.rawQuery("SELECT MAX(id)+1 as last_inserted_id


FROM Product"); var id = maxIdResult.first["last_inserted_id"];

var result = menunggu db.rawInsert(


"MASUKKAN Ke Dalam Produk (id, nama, deskripsi, harga, gambar)"
"
NILAI (?, ?, ?, ?, ?)",
[id, nama produk, deskripsi produk, harga produk,
gambar produk] );

mengembalikan hasil;
}

perbarui (Produk produk) async { final db


= menunggu basis data;

var result = await db.update("Product", product.toMap(), where: "id = ?",


whereArgs: [product.id]);

mengembalikan hasil;
}

hapus (int id) async { final db


= menunggu basis data;

db.delete("Produk", di mana: "id = ?", di manaArgs: [id]);

132
Machine Translated by Google

Berdebar

}
}

• Mengubah metode utama untuk mendapatkan informasi produk.

void main()
{ runApp(MyApp(produk: SQLiteDbProvider.db.getAllProducts()));
}

• Di sini, kami telah menggunakan metode getAllProducts untuk mengambil semua produk dari database.

• Jalankan aplikasi dan lihat hasilnya. Ini akan mirip dengan contoh sebelumnya, Mengakses API layanan
Produk, kecuali informasi produk disimpan dan diambil dari database SQLite lokal.

Toko Api Awan


Firebase adalah platform pengembangan aplikasi BaaS. Ini menyediakan banyak fitur untuk mempercepat
pengembangan aplikasi seluler seperti layanan otentikasi, penyimpanan cloud, dll. Salah satu fitur utama
Firebase adalah Cloud Firestore, database NoSQL waktu nyata berbasis cloud.

Flutter menyediakan paket khusus, cloud_firestore untuk memprogram dengan Cloud Firestore. Mari kita
buat toko produk online di Cloud Firestore dan buat aplikasi untuk mengakses toko produk.

• Buat aplikasi Flutter baru di studio Android, product_firebase_app

• Ganti kode startup default (main.dart) dengan kode product_rest_app kami .

• Salin file Product.dart dari product_rest_app ke folder lib.

kelas Produk
{ nama String akhir;
deskripsi String akhir; harga int
akhir; gambar String akhir;

Produk(ini.nama, ini.deskripsi, ini.harga, ini.gambar);

pabrik Product.fromMap(Map<String, dynamic> json) { return


Product( json['nama'], json['deskripsi'], json['harga'], json['gambar'], );

}
}

• Salin folder aset dari product_rest_app ke product_firebase_app dan tambahkan aset di dalam file
pubspec.yaml

berdebar:

133
Machine Translated by Google

Berdebar

aktiva:
- aset/appimages/floppy.png - aset/
appimages/iphone.png - aset/appimages/
laptop.png - aset/appimages/
pendrive.png - aset/appimages/pixel.png -
aset/appimages/tablet.png

• Konfigurasikan paket cloud_firestore di file pubspec.yaml seperti gambar di bawah ini:

dependensi:
cloud_firestore: ^0.9.13+1

• Di sini, gunakan paket cloud_firestore versi terbaru.

• Android studio akan memberi tahu bahwa pubspec.yaml diperbarui seperti yang ditampilkan di sini:

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan mengonfigurasinya
dengan benar untuk aplikasi tersebut.

• Buat proyek di Firebase menggunakan langkah-langkah berikut:

• Membuat A Firebase akun oleh memilih Bebas rencana pada

https://firebase.google.com/pricing/

• Setelah akun Firebase dibuat, itu akan dialihkan ke halaman ikhtisar proyek. Itu mencantumkan semua
proyek berbasis Firebase dan memberikan opsi untuk membuat proyek baru.

• Klik Tambahkan proyek dan itu akan membuka halaman pembuatan proyek.

• Masukkan db aplikasi produk sebagai nama proyek dan klik opsi Buat proyek.

• Pergi ke *Firebase console.

• Klik Ikhtisar proyek. Ini membuka halaman ikhtisar proyek.

• Klik ikon android. Ini akan membuka pengaturan proyek khusus untuk pengembangan Android.

• Masukkan nama Paket Android, com.tutorialspoint.flutterapp.product_firebase_app

• Klik Daftar Aplikasi. Ini menghasilkan file konfigurasi proyek, google_service.json

• Unduh google_service.json lalu pindahkan ke direktori android/app proyek. File ini adalah koneksi antara
aplikasi kita dan Firebase.

• Buka android/app/build.gradle dan sertakan kode berikut:

terapkan plugin: 'com.google.gms.google-services'

• Buka android/build.gradle dan sertakan konfigurasi berikut:

134
Machine Translated by Google

Berdebar

buildscript
{ repositori { // ...

dependencies
{ // ...
classpath 'com.google.gms:google-services:3.2.1' // baru
}
}

Di sini, plugin dan jalur kelas digunakan untuk membaca file google_service.json.

• Buka android/app/build.gradle dan sertakan juga kode berikut.

android
{ defaultConfig {
...
multiDexEnabled benar
}
...
}

dependensi {
...
kompilasi 'com.android.support: multidex:1.0.3'
}

Ketergantungan ini memungkinkan aplikasi android untuk menggunakan beberapa


fungsionalitas dex.

• Ikuti langkah-langkah selanjutnya di Firebase Console atau lewati saja.

• Buat toko produk di proyek yang baru dibuat menggunakan langkah-langkah berikut:

• Buka konsol Firebase.

• Buka proyek yang baru dibuat.

• Klik opsi Database di menu sebelah kiri.

• Klik opsi Buat basis data.

• Klik Mulai dalam mode uji lalu Aktifkan

• Klik Tambahkan koleksi. Masukkan produk sebagai nama koleksi, lalu klik Berikutnya.

• Masukkan informasi produk sampel seperti yang ditunjukkan pada gambar di sini:

135
Machine Translated by Google

Berdebar

• Tambahkan informasi produk tambahan menggunakan opsi Tambahkan dokumen .

• Buka file main.dart dan impor file plugin Cloud Firestore dan hapus paket http.

impor 'paket: cloud_firestore/cloud_firestore.dart';

• Hapus parseProducts dan perbarui fetchProducts untuk mengambil produk dari Cloud
Firestore, bukan API layanan Produk

Streaming<QuerySnapshot> fetchProducts() {
return Firestore.instance.collection('product').snapshots();
}

• Di sini, metode Firestore.instance.collection digunakan untuk mengakses koleksi produk yang tersedia di
cloud store. Firestore.instance.collection menyediakan banyak opsi untuk memfilter koleksi untuk mendapatkan
dokumen yang diperlukan. Namun, kami belum menerapkan filter apa pun untuk mendapatkan semua informasi
produk.

• Cloud Firestore menyediakan koleksi melalui konsep Dart Stream sehingga memodifikasi jenis produk di widget MyApp
dan MyHomePage dari Future<list<Product>> menjadi Stream<QuerySnapshot>.

136
Machine Translated by Google

Berdebar

• Ubah metode build widget MyHomePage untuk menggunakan StreamBuilder sebagai gantinya
FutureBuilder.

@mengesampingkan

Widget build(BuildContext context) { return


Scaffold( appBar: AppBar(title: Text("Product
Navigation")), body: Center( child:
StreamBuilder<QuerySnapshot>( stream: products, builder:
(context, snapshot) {

if (snapshot.hasError) print(snapshot.error);

if(snapshot.hasData)
{ Daftar<DocumentSnapshot> dokumen = snapshot.data.dokumen;
Daftar<Produk> item = Daftar<Produk>();

for(var i = 0; i < documents.length; i++)


{ DocumentSnapshot document = documents[i];

item.tambahkan(Produk.dariPeta(dokumen.data));
}

kembalikan ProductBoxList(item: item); } else


{ return Center(anak: CircularProgressIndicator());

} }, ), ));

• Di sini, kami telah mengambil informasi produk sebagai tipe List<DocumentSnapshot>.


Karena widget kami, ProductBoxList tidak kompatibel dengan dokumen, kami telah mengonversi
dokumen menjadi tipe List<Product> dan selanjutnya menggunakannya.
• Terakhir, jalankan aplikasi dan lihat hasilnya. Karena, kami telah menggunakan informasi produk
yang sama dengan aplikasi SQLite dan hanya mengubah media penyimpanan, aplikasi yang
dihasilkan terlihat identik dengan aplikasi aplikasi SQLite .

137
Machine Translated by Google

16. Flutter – Internasionalisasi Berdebar

Saat ini, aplikasi seluler digunakan oleh pelanggan dari berbagai negara dan akibatnya, aplikasi diharuskan menampilkan
konten dalam berbagai bahasa. Mengaktifkan aplikasi untuk bekerja dalam berbagai bahasa disebut Menginternasionalkan
aplikasi.

Agar aplikasi bekerja dalam bahasa yang berbeda, pertama-tama aplikasi harus menemukan lokal saat ini dari sistem
tempat aplikasi berjalan dan kemudian perlu menunjukkan kontennya di lokal tersebut, dan proses ini disebut Lokalisasi.

Framework Flutter menyediakan tiga kelas dasar untuk pelokalan dan kelas utilitas ekstensif yang diturunkan dari kelas
dasar untuk melokalkan aplikasi.

Kelas dasar adalah sebagai berikut:

• Lokal - Lokal adalah kelas yang digunakan untuk mengidentifikasi bahasa pengguna. Misalnya, en-us
mengidentifikasi bahasa Inggris Amerika dan dapat dibuat sebagai:

Lokal in_local = Lokal('dalam', 'AS')

Di sini, argumen pertama adalah kode bahasa dan argumen kedua adalah kode negara.
Contoh lain untuk membuat lokal Argentina Spanyol (es-ar) adalah sebagai berikut:

Lokal es_locale = Lokal('es', 'AR')

• Pelokalan - Pelokalan adalah widget generik yang digunakan untuk menyetel Lokal dan sumber daya yang
dilokalkan dari anaknya.

kelas CustomLocalizations
{ CustomLocalizations(this.locale);

lokal lokal terakhir;

static CustomLocalizations of(BuildContext context) {


return Localizations.of<CustomLocalizations>(context, CustomLocalizations);

Peta statis<String, Peta<String, String>> _resources = {


'en':
{ 'title': 'Demo', 'message':
'Hello World'
},
'en':
{ 'title': 'Demo', 'message': 'Hello
World',

}, };

String dapatkan judul


{ return _resources[locale.languageCode]['title'];
}

138
Machine Translated by Google

Berdebar

String dapatkan pesan


{ return _resources[locale.languageCode]['message'];
}
}

• Di sini, CustomLocalizations adalah kelas khusus baru yang dibuat khusus untuk mendapatkan konten lokal
tertentu (judul dan pesan) untuk widget. metode menggunakan kelas Pelokalan untuk mengembalikan kelas
CustomLocalizations baru.

• LocalizationsDelegate<T> - LocalizationsDelegate<T> adalah kelas pabrik tempat widget Pelokalan dimuat. Ini
memiliki tiga metode over-ridable:

• isSupported - Menerima lokal dan mengembalikan apakah lokal yang ditentukan adalah
didukung atau tidak.

@override
bool isSupported(Locale locale) => ['en',
'es'].contains(locale.languageCode);

Di sini, delegasi hanya bekerja untuk en dan es locale.

• load - Menerima lokal dan mulai memuat sumber daya untuk lokal yang ditentukan.

@mengesampingkan

Beban <CustomLocalizations> masa depan (Lokal lokal) {


kembali
SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale)); }

Di sini, metode load mengembalikan CustomLocalizations. CustomLocalizations yang dikembalikan


dapat digunakan untuk mendapatkan nilai judul dan pesan dalam bahasa Inggris dan Spanyol.

• shouldReload - Menentukan apakah pemuatan ulang CustomLocalizations diperlukan saat widget Pelokalan
dibuat ulang.

@override
bool shouldReload(CustomLocalizationsDelegate old) => false;

• Kode lengkap CustomLocalizationDelegate adalah sebagai berikut:

kelas CustomLocalizationsDelegate meluas


LocalizationsDelegate<CustomLocalizations> { const
CustomLocalizationsDelegate();

@override
bool didukung(LocalLocal) => ['kami',
'es'].contains(locale.languageCode);

@mengesampingkan

Beban <CustomLocalizations> masa depan (Lokal lokal) {


kembali
SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));

139
Machine Translated by Google

Berdebar

@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
}

Secara umum, aplikasi Flutter didasarkan pada dua widget level root, MaterialApp atau WidgetsApp. Flutter
menyediakan pelokalan siap pakai untuk kedua widget dan keduanya adalah MaterialLocalizations dan
WidgetsLocaliations. Selanjutnya, Flutter juga menyediakan delegasi untuk memuat MaterialLocalizations
dan GlobalMaterialLocalizations.delegate. WidgetsLocaliations dan mereka serta adalah

GlobalWidgetsLocalizations.delegate

Mari kita buat aplikasi berkemampuan internasionalisasi sederhana untuk menguji dan memahami konsepnya.

• Buat aplikasi flutter baru, flutter_localization_app

• Flutter mendukung internasionalisasi menggunakan paket flutter eksklusif, flutter_localizations. Idenya


adalah untuk memisahkan konten lokal dari SDK utama.
Buka pubspec.yaml dan tambahkan kode di bawah ini untuk mengaktifkan paket internasionalisasi:

dependensi:
bergetar:
sdk: bergetar
flutter_localizations: sdk:
bergetar

• Android studio akan menampilkan peringatan berikut bahwa pubspec.yaml telah diperbarui.

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan
mengonfigurasinya dengan benar untuk aplikasi tersebut.

• Impor paket flutter_localizations di main.dart sebagai berikut:

impor 'paket:flutter_localizations/flutter_localizations.dart'; import 'package:flutter/


foundation.dart' tampilkan SynchronousFuture;

• Di sini, tujuan SynchronousFuture adalah untuk memuat pelokalan khusus secara sinkron.

• Buat pelokalan khusus dan delegasinya yang sesuai seperti yang ditentukan di bawah ini:

kelas CustomLocalizations
{ CustomLocalizations(this.locale);

lokal lokal terakhir;

static CustomLocalizations of(BuildContext context) {


return Localizations.of<CustomLocalizations>(context,
CustomLocalizations);
}

140
Machine Translated by Google

Berdebar

Peta statis<String, Peta<String, String>> _resources = {


'en':
{ 'title': 'Demo',
'message': 'Hello World'
},
'en':
{ 'title': 'Demo', 'message': 'Hello
World',

}, };

String dapatkan judul


{ return _resources[locale.languageCode]['title'];
}

String dapatkan pesan


{ return _resources[locale.languageCode]['message'];
}
}

kelas CustomLocalizationsDelegate meluas


LocalizationsDelegate<CustomLocalizations> { const
CustomLocalizationsDelegate();

@override
bool didukung(LocalLocal) => ['kami',
'es'].contains(locale.languageCode);

@mengesampingkan

Beban <CustomLocalizations> masa depan (Lokal lokal) {


kembali
SynchronousFuture<CustomLocalizations>(CustomLocalizations(locale));
}

@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
}

• Di sini, CustomLocalizations dibuat untuk mendukung pelokalan untuk judul dan pesan dalam aplikasi
dan CustomLocalizationsDelegate digunakan untuk memuat CustomLocalizations.

• Tambahkan delegasi untuk MaterialApp, WidgetsApp, dan CustomLocalization menggunakan properti


MaterialApp, localizationsDelegate, dansupportLocales seperti yang ditentukan di bawah ini:

localizationsDelegate: [ const
CustomLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
SupportLocales: [ const
Locale('en', ''),

141
Machine Translated by Google

Berdebar

const Lokal('es', ''),


],

• Gunakan metode CustomLocalizations, of untuk mendapatkan nilai judul dan pesan yang dilokalkan
dan gunakan di tempat yang tepat seperti yang ditentukan di bawah ini:

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@mengesampingkan

Pembuatan widget(konteks BuildContext) { return


Scaffold( appBar: AppBar(

judul: Teks(CustomLocalizations .of(context) .title),

),
body:
Center( anak:
Kolom( mainAxisAlignment: MainAxisAlignment.center,
anak: <Widget>[ Text( CustomLocalizations .of(context)

.pesan, ), ], ), ), );

• Di sini, kami telah memodifikasi kelas MyHomePage dari StatefulWidget menjadi StatelessWidget untuk
alasan kesederhanaan dan menggunakan CustomLocalizations untuk mendapatkan judul dan pesan.

• Mengkompilasi dan menjalankan aplikasi. Aplikasi akan menampilkan kontennya dalam bahasa Inggris.

• Tutup aplikasi. Buka Pengaturan -> Sistem -> Bahasa dan Input ->
Bahasa*

• Klik Tambahkan opsi bahasa dan pilih Spanyol. Ini akan menginstal bahasa Spanyol dan kemudian
mencantumkannya sebagai salah satu opsi.

• Pilih bahasa Spanyol dan pindahkan ke atas bahasa Inggris. Ini akan ditetapkan sebagai bahasa Spanyol sebagai
bahasa pertama dan semuanya akan diubah menjadi teks Spanyol.

• Sekarang luncurkan kembali aplikasi internasionalisasi dan Anda akan melihat judul dan
pesan dalam bahasa spanyol.

• Kita dapat mengembalikan bahasa ke bahasa Inggris dengan memindahkan opsi bahasa Inggris di atas bahasa Spanyol
pilihan dalam pengaturan.

• Hasil aplikasi (dalam bahasa Spanyol) ditunjukkan pada tangkapan layar di bawah ini:

142
Machine Translated by Google

Berdebar

Menggunakan Paket intl

Flutter menyediakan paket intl untuk semakin menyederhanakan pengembangan aplikasi seluler yang
dilokalkan. paket intl menyediakan metode dan alat khusus untuk semi-otomatis menghasilkan pesan khusus
bahasa.

Mari kita buat aplikasi lokal baru dengan menggunakan paket intl dan pahami konsepnya.

• Buat aplikasi flutter baru, flutter_intl_app

• Buka pubspec.yaml dan tambahkan detail paket.

dependensi:
bergetar:
sdk: bergetar
flutter_localizations: sdk:
bergetar
intl: ^0.15.7
intl_translation: ^0.17.3

143
Machine Translated by Google

Berdebar

• Android studio akan menampilkan alert seperti dibawah ini yang menginformasikan bahwa pubspec.yaml
diperbarui.

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan
mengonfigurasinya dengan benar untuk aplikasi tersebut.

• Salin main.dart dari contoh sebelumnya, flutter_internationalization_app

• Impor paket intl seperti yang ditunjukkan di bawah ini:

impor 'paket:intl/intl.dart';

• Perbarui kelas CustomLocalization seperti yang ditunjukkan pada kode di bawah ini:

kelas CustomLocalizations {
masa depan statis<CustomLocalizations> memuat (Lokal lokal) {
nama String akhir = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(nama);

kembali initializeMessages(localeName).kemudian((_) {
Intl.defaultLocale = namalokal; kembalikan
CustomLocalizations(); });

static CustomLocalizations of(BuildContext context) {


return Localizations.of<CustomLocalizations>(context,
CustomLocalizations);
}

String get title { return


Intl.message( 'Demo',
name: 'title', desc: 'Title
for the Demo
application', );

String dapatkan pesan{


return Intl.message( 'Halo
Dunia', nama: 'pesan',
desc: 'Pesan untuk
aplikasi Demo',);

}
}

kelas CustomLocalizationsDelegate meluas


LocalizationsDelegate<CustomLocalizations> { const
CustomLocalizationsDelegate();

@mengesampingkan

144
Machine Translated by Google

Berdebar

bool didukung(LocalLocal) => ['en',


'es'].contains(locale.languageCode);

@ganti
Future<CustomLocalizations> load(Locale locale) { return
CustomLocalizations.load(locale);
}

@override
bool shouldReload(CustomLocalizationsDelegate old) => false;
}

• Di sini, kami telah menggunakan tiga metode dari paket intl alih-alih metode khusus.
Kalau tidak, konsepnya sama.

• Intl.canonicalizedLocale - Digunakan untuk mendapatkan nama lokal yang benar.

• Intl.defaultLocale - Digunakan untuk menyetel lokal saat ini.

• Intl.message - Digunakan untuk mendefinisikan pesan baru.

• impor file l10n/messages_all.dart . Kami akan segera membuat file ini.

import 'l10n/messages_all.dart';

• Sekarang, buat folder, lib/l10n

• Buka prompt perintah dan buka direktori root aplikasi (di mana pubspec.yaml
tersedia) dan jalankan perintah berikut:

paket bergetar pub menjalankan intl_translation:extract_to_arb --output dir=lib/l10n lib/


main.dart

• Di sini, perintah akan menghasilkan, file intl_message.arb, sebuah template untuk membuat pesan di
lokasi yang berbeda. Isi filenya adalah sebagai berikut:

{
"@@last_modified": "2019-04-19T02:04:09.627551", "title":
"Demo", "@title": { "description": "Judul untuk aplikasi Demo",
"type": "text ", "placeholder": {} }, "message": "Halo Dunia",
"@message": {

"description": "Pesan untuk aplikasi Demo", "type": "text",


"placeholders": {}

}
}

• Salin intl_message.arb dan buat file baru, intl_en.arb

• Salin intl_message.arb dan buat file baru, intl_es.arb dan ubah isinya ke bahasa Spanyol seperti yang
ditunjukkan di bawah ini:

145
Machine Translated by Google

Berdebar

{
"@@last_modified": "2019-04-19T02:04:09.627551", "title":
"Manifestación", "@title": { "description": "Judul untuk aplikasi
Demo", "type": "text ", "placeholder": {} }, "message": "Hola
Mundo", "@message": {

"description": "Pesan untuk aplikasi Demo", "type": "text",


"placeholders": {}

}
}

• Sekarang, jalankan perintah berikut untuk membuat file pesan terakhir, messages_all.dart

paket flutter pub menjalankan intl_translation:generate_from_arb --output dir=lib\l10n --no-


use-deferred-loading lib\main.dart lib\l10n\intl_en.arb lib\l10n\intl_es.arb

• Mengkompilasi dan menjalankan aplikasi. Ini akan bekerja mirip dengan aplikasi di atas, flutter_localization_app.

146
Machine Translated by Google

Berdebar
17. Flutter – Pengujian

Pengujian adalah fase yang sangat penting dalam siklus hidup pengembangan aplikasi. Ini memastikan bahwa
aplikasi berkualitas tinggi. Pengujian membutuhkan perencanaan dan pelaksanaan yang cermat. Ini juga
merupakan fase pengembangan yang paling memakan waktu.

Bahasa Dart dan framework Flutter menyediakan dukungan ekstensif untuk pengujian otomatis aplikasi.

Jenis Pengujian
Umumnya, tiga jenis proses pengujian tersedia untuk menguji aplikasi sepenuhnya.
Mereka adalah sebagai berikut:

Pengujian Unit
Pengujian unit adalah metode termudah untuk menguji aplikasi. Ini didasarkan pada memastikan kebenaran
sepotong kode (fungsi, secara umum) atau metode kelas. Tapi, itu tidak mencerminkan lingkungan nyata dan
selanjutnya, adalah pilihan paling sedikit untuk menemukan bug.

Pengujian Widget
Pengujian widget didasarkan pada memastikan kebenaran pembuatan widget, rendering, dan interaksi
dengan widget lain seperti yang diharapkan. Ini melangkah lebih jauh dan menyediakan lingkungan waktu
nyata untuk menemukan lebih banyak bug.

Tes integrasi
Pengujian integrasi melibatkan pengujian unit dan pengujian widget bersama dengan komponen eksternal
aplikasi seperti database, layanan web, dll., Ini mensimulasikan atau mengolok-olok lingkungan nyata untuk
menemukan hampir semua bug, tetapi ini adalah proses yang paling rumit.

Flutter memberikan dukungan untuk semua jenis pengujian. Ini memberikan dukungan ekstensif dan eksklusif
untuk pengujian Widget. Pada bab ini, kita akan membahas pengujian widget secara detail.

Pengujian Widget
Framework pengujian Flutter menyediakan metode testWidgets untuk menguji widget. Itu menerima dua
argumen:
• Deskripsi tes
• Kode uji

testWidgets('deskripsi pengujian: temukan widget', '<kode pengujian>');

147
Machine Translated by Google

Berdebar

Langkah Terlibat
Pengujian Widget melibatkan tiga langkah berbeda:

• Render widget di lingkungan pengujian.

• WidgetTester adalah kelas yang disediakan oleh framework pengujian Flutter untuk membuat dan merender
widget. metode pumpWidget dari kelas WidgetTester menerima widget apa pun dan merendernya di
lingkungan pengujian.

testWidgets('menemukan contoh spesifik', (penguji WidgetTester) async {


menunggu tester.pumpWidget(MaterialApp( home:
Scaffold( body: Text('Hello'),

),
));
});

• Menemukan widget, yang perlu kita uji.

• Framework Flutter menyediakan banyak opsi untuk menemukan widget yang dirender di lingkungan
pengujian dan umumnya disebut Finder. Pencari yang paling sering digunakan adalah find.text,
find.byKey, dan find.byWidget
• find.text menemukan widget yang berisi teks yang ditentukan.

find.text('Halo')

• find.byKey temukan widget dengan kunci spesifiknya.

temukan.byKey('rumah')

• find.byWidget temukan widget dengan variabel instannya

temukan.denganWidget(homeWidget)

• Memastikan widget berfungsi seperti yang diharapkan.

• Framework Flutter menyediakan banyak opsi untuk mencocokkan widget dengan widget yang diharapkan
dan biasanya disebut Matcher. Kami dapat menggunakan metode ekspektasi yang disediakan oleh
kerangka pengujian untuk mencocokkan widget, yang kami temukan di langkah kedua dengan widget
yang kami harapkan dengan memilih salah satu pencocokan. Beberapa pencocokan penting adalah
sebagai berikut:

•findOneWidget - memverifikasi widget tunggal ditemukan.

mengharapkan(menemukan.teks('Halo'), menemukanSatuWidget);

• foundNothing - memverifikasi tidak ada widget yang ditemukan.

expect(find.text('Halo Dunia'), tidak menemukanApa pun);

•findWidgets - memverifikasi lebih dari satu widget ditemukan.

148
Machine Translated by Google

Berdebar

mengharapkan(menemukan.teks('Simpan'), menemukanWidgets);

•findNWidgets - memverifikasi N jumlah widget ditemukan.

mengharapkan(menemukan.teks('Simpan'), menemukanNWidgets(2));

Kode tes lengkap adalah sebagai berikut:

testWidgets('temukan halo widget', (penguji WidgetTester) async { menunggu


tester.pumpWidget(MaterialApp( home: Scaffold( body: Text('Hello'),

),
));

mengharapkan(menemukan.teks('Halo'), menemukanSatuWidget);
});

Di sini, kami merender widget MaterialApp dengan teks Halo menggunakan widget Teks di badannya.
Kemudian, kami menggunakan find.text untuk menemukan widget dan kemudian mencocokkannya menggunakan foundOneWidget.

Contoh Kerja
Mari kita membuat aplikasi bergetar sederhana dan menulis tes widget untuk lebih memahami langkah-langkah yang
terlibat dan konsepnya.

• Buat aplikasi flutter baru, flutter_test_app di studio Android.

• Buka widget_test.dart di folder test. Ini memiliki kode pengujian sampel seperti yang diberikan di bawah ini:

testWidgets('Counter increments smoke test', (penguji WidgetTester) async {


// Bangun aplikasi kita dan picu bingkai. menunggu
tester.pumpWidget(MyApp());

// Pastikan penghitung kita mulai dari 0.


expect(find.text('0'), foundOneWidget);
mengharapkan(menemukan.teks('1'), menemukanTidak ada);

// Ketuk ikon '+' dan picu bingkai. menunggu


tester.tap(find.byIcon(Icons.add)); menunggu tester.pump();

// Pastikan penghitung kita bertambah.


mengharapkan(menemukan.teks('0'), menemukanTidak
ada); mengharapkan(menemukan.teks('1'),
menemukanSatuWidget); });

• Di sini, kode uji melakukan fungsi-fungsi berikut:

• Merender widget MyApp menggunakan tester.pumpWidget

• Memastikan bahwa penghitung awalnya nol menggunakan menemukanSatuWidget dan menemukanTidak ada
pertandingan.

149
Machine Translated by Google

Berdebar

• Menemukan tombol counter increment menggunakan metode find.byIcon.

• Ketuk tombol counter increment menggunakan metode tester.tap.

• Memastikan penghitung dinaikkan dengan menggunakanfindOneWidget danfindNothing


pertandingan.

• Mari kita ketuk lagi tombol kenaikan penghitung dan kemudian periksa apakah penghitung dinaikkan
menjadi dua.

menunggu tester.tap(find.byIcon(Icons.add)); menunggu


tester.pump();

mengharapkan(menemukan.teks('2'), menemukanSatuWidget);

• Klik menu Jalankan.

• Klik tes di opsi widget_test.dart. Ini akan menjalankan pengujian dan melaporkan hasilnya di jendela
hasil.

150
Machine Translated by Google

18. Flutter – Penerapan Berdebar

Bab ini menjelaskan cara menerapkan aplikasi Flutter di platform Android dan iOS.

Aplikasi Android
• Ubah nama aplikasi menggunakan entri android:label di file manifes android.
File manifes aplikasi Android, AndroidManifest.xml terletak di <app dir>/android/app/src/main. Ini berisi
seluruh detail tentang aplikasi android.
Kita dapat mengatur nama aplikasi menggunakan entri android:label.

• Ubah ikon peluncur menggunakan entri android:icon di file manifes.

• Menandatangani aplikasi menggunakan opsi standar seperlunya

• Aktifkan Proguard dan Obfuscation menggunakan opsi standar, jika perlu.

• Buat file APK rilis dengan menjalankan perintah di bawah ini:

cd /path/to/my/application flutter
build apk

• Anda dapat melihat output seperti yang ditunjukkan di bawah ini:

Menginisialisasi gradle... 8,6 detik

Menyelesaikan dependensi... 19,9 detik

Memanggil transformasi artefak JAR yang dapat diejek untuk membuat


file: /Users/.gradle/caches/transforms-1/files-1.1/android.jar/
c30932f130afbf3fd90c131ef9069a0b/android.jar dengan input /Users/Library/
Android/sdk/platforms/android-28 /android.jar Menjalankan tugas Gradle
'assembleRelease'...
Menjalankan tugas Gradle 'assembleRelease'... Selesai 85,7 detik

Bangun build/app/outputs/apk/release/app-release.apk (4,8MB).

• Instal APK di perangkat menggunakan perintah berikut:

instalasi bergetar

• Publikasikan aplikasi ke Google Playstore dengan membuat appbundle dan mendorongnya ke


playstore menggunakan metode standar.

bundel aplikasi build flutter

Aplikasi iOS
• Daftarkan aplikasi iOS di App Store Connect menggunakan metode standar. Simpan =Bundle ID yang
digunakan saat mendaftar aplikasi.

• Perbarui nama Tampilan dalam pengaturan proyek XCode untuk mengatur nama aplikasi.

151
Machine Translated by Google

Berdebar

• Perbarui Pengidentifikasi Bundel dalam pengaturan proyek XCode untuk mengatur id bundel, yang kami
digunakan pada langkah 1.

• Tanda kode seperlunya menggunakan metode standar.

• Tambahkan ikon aplikasi baru seperlunya menggunakan metode standar.

• Hasilkan file IPA menggunakan perintah berikut:

bergetar membangun ios

• Sekarang, Anda dapat melihat output berikut:

Membuat com.example.MyApp untuk perangkat (rilis ios)...


Menandatangani iOS secara otomatis untuk penerapan perangkat menggunakan tim pengembangan
tertentu dalam proyek Xcode: Menjalankan Xcode build...
23,5 detik

......................

• Uji aplikasi dengan mendorong aplikasi, file IPA ke dalam TestFlight menggunakan metode
standar.

• Terakhir, dorong aplikasi ke App Store menggunakan metode standar.

152
Machine Translated by Google

19. Flutter – Alat Pengembangan Berdebar

Bab ini menjelaskan tentang alat pengembangan Flutter secara mendetail. Rilis stabil pertama dari toolkit pengembangan
lintas platform dirilis pada 4 Desember 2018, Flutter 1.0.
Yah, Google terus berupaya meningkatkan dan memperkuat kerangka kerja Flutter dengan berbagai alat pengembangan.

Set Widget
Google memperbarui untuk set widget Material dan Cupertino untuk memberikan kualitas piksel sempurna dalam desain
komponen. Versi mendatang dari flutter 1.2 akan dirancang untuk mendukung event keyboard desktop dan dukungan
mouse hover.

Pengembangan Flutter dengan Kode Visual Studio


Visual Studio Code mendukung pengembangan flutter dan menyediakan pintasan ekstensif untuk pengembangan yang
cepat dan efisien. Beberapa fitur utama yang disediakan oleh Visual Studio Code untuk pengembangan flutter tercantum
di bawah ini:

• Bantuan kode - Saat Anda ingin memeriksa opsi, Anda dapat menggunakan Ctrl+Spasi untuk mendapatkan a
daftar opsi penyelesaian kode.

• Perbaikan cepat - Ctrl+. adalah alat perbaikan cepat untuk membantu memperbaiki kode.

• Pintasan saat Pengkodean

• Memberikan dokumentasi terperinci dalam komentar.

• Men-debug pintasan.

• Hot restart

Dart DevTools
Kita dapat menggunakan Android Studio atau Visual Studio Code, atau IDE lainnya untuk menulis kode kita dan
memasang plugin. Tim pengembangan Google sedang mengerjakan alat pengembangan lain yang disebut Dart DevTools
Ini adalah rangkaian pemrograman berbasis web. Ini mendukung platform Android dan iOS. Ini didasarkan pada tampilan
garis waktu sehingga pengembang dapat dengan mudah menganalisis aplikasi mereka.

Instal DevTools
Untuk menginstal DevTools, jalankan perintah berikut di konsol Anda:

paket flutter pub global mengaktifkan devtools

Sekarang Anda dapat melihat output berikut:

Menyelesaikan dependensi... + args


1.5.1 + async 2.2.0

153
Machine Translated by Google

Berdebar

+ charcode 1.1.2 +
codemirror 0.5.3+5.44.0
+ koleksi 1.14.11
+ konversi 2.1.1 +
devtools 0.0.16
+ devtools_server 0.0.2 + http
0.12.0+2 + http_parser 3.1.3
+ intl 0.15.8

+ js 0.6.1+1 +
target 1.1.7
+ pantomim 0.9.6+2
.................
.................

Alat dev yang dapat dieksekusi diinstal.

Alat dev yang diaktifkan 0.0.16.

Jalankan Server

Anda dapat menjalankan server DevTools menggunakan perintah berikut:

paket flutter pub global menjalankan devtools

Sekarang, Anda akan mendapatkan respons yang mirip dengan ini,

Melayani DevTools di http://127.0.0.1:9100

Mulai Aplikasi Anda


Buka aplikasi Anda, buka simulator dan jalankan menggunakan perintah berikut:

lari bergetar --observatory-port=9200

Sekarang, Anda terhubung ke DevTools.

Mulai DevTools di Browser


Sekarang akses url di bawah ini di browser, untuk memulai DevTools:

http://localhost:9100/?port=9200

Anda akan mendapatkan respons seperti yang ditunjukkan di bawah ini:

154
Machine Translated by Google

Berdebar

Berkibar SDK
Untuk memperbarui Flutter SDK, gunakan perintah berikut:

peningkatan bergetar

Anda dapat melihat output seperti yang ditunjukkan di bawah ini:

Untuk mengupgrade paket Flutter, gunakan perintah berikut:

peningkatan paket flutter

Anda dapat melihat respons berikut,

Menjalankan "peningkatan paket flutter" di my_app... 7.4s

Inspektur Flutter
Ini digunakan untuk menjelajahi pohon widget flutter. Untuk mencapai ini, jalankan perintah di bawah ini di
konsol Anda,

155
Machine Translated by Google

Berdebar

flutter run --track-widget-creation

Anda dapat melihat output seperti yang ditunjukkan di bawah ini:

Meluncurkan lib/main.dart di iPhone X dalam mode debug...

ÿMerakit sumber daya Flutter... 3,6 detik

Menyusun, menautkan, dan menandatangani... 6,8 detik

Pembuatan Xcode selesai. 14,2 detik

2.904 md (!)

Untuk memuat ulang perubahan saat menjalankan, tekan "r". Untuk hot restart (dan membangun kembali status),
tekan "R".
Debugger Observatory dan profiler di iPhone X tersedia di: http://127.0.0.1:50399/ Untuk pesan
bantuan yang lebih mendetail, tekan "h". Untuk melepaskan, tekan "d"; untuk keluar, tekan "q".

Sekarang pergi ke url, http://127.0.0.1:50399/ Anda bisa melihat hasil berikut:

156
Machine Translated by Google

20. Flutter – Menulis Aplikasi Tingkat Lanjut Berdebar

Dalam bab ini, kita akan mempelajari cara menulis aplikasi seluler lengkap, kalkulator_pengeluaran. Tujuan
dari kalkulator_pengeluaran adalah untuk menyimpan informasi pengeluaran kita. Fitur lengkap dari aplikasi ini
adalah sebagai berikut:

• Daftar biaya
• Formulir untuk memasukkan biaya baru
• Pilihan untuk mengedit/menghapus pengeluaran yang ada
• Total pengeluaran kapan saja.

Kita akan memprogram aplikasi expense_calculator menggunakan fitur-fitur canggih kerangka kerja Flutter
yang disebutkan di bawah.

• Penggunaan ListView tingkat lanjut untuk menampilkan daftar pengeluaran

• Pemrograman bentuk
• Pemrograman basis data SQLite untuk menyimpan pengeluaran kita
• manajemen keadaan scoped_model untuk menyederhanakan pemrograman kita.

Mari kita mulai memprogram aplikasi expense_calculator .

• Buat aplikasi Flutter baru, expense_calculator di Android studio.

• Buka pubspec.yaml dan tambahkan dependensi paket.

dependensi:
bergetar:
sdk: bergetar

sqflite: ^1.1.0
path_provider: ^0.5.0+1
scoped_model: ^1.0.1 intl: apa
saja

• Perhatikan poin-poin berikut ini:

• sqflite digunakan untuk pemrograman basis data SQLite. •


path_provider digunakan untuk mendapatkan jalur aplikasi khusus sistem.
• scoped_model digunakan untuk manajemen status.
• intl digunakan untuk format tanggal

• Android studio akan menampilkan peringatan berikut bahwa pubspec.yaml telah diperbarui.

• Klik opsi Dapatkan dependensi. Studio Android akan mendapatkan paket dari Internet dan
mengonfigurasinya dengan benar untuk aplikasi tersebut.

157
Machine Translated by Google

Berdebar

• Hapus kode yang ada di main.dart

• Tambahkan file baru, Expense.dart untuk membuat kelas Expense. Kelas biaya akan memiliki properti dan
metode di bawah ini.

• properti: id - id unik untuk mewakili entri pengeluaran dalam database SQLite.


• properti: jumlah - Jumlah yang dibelanjakan.
• properti: tanggal - Tanggal saat jumlah dibelanjakan.
• properti: kategori - Kategori mewakili area di mana jumlah dibelanjakan.
misalnya Makanan, Perjalanan, dll.,

• formattedDate - Digunakan untuk memformat properti tanggal


• fromMap - Digunakan untuk memetakan bidang dari tabel database ke properti di
objek pengeluaran dan untuk membuat objek pengeluaran baru

biaya pabrik.fromMap(Peta<String, dynamic> data) { return


Expense( data['id'], data['amount'], DateTime.parse(data['date']),
data['category']

);
}

• toMap - Digunakan untuk mengonversi objek pengeluaran menjadi Dart Map, yang selanjutnya dapat
digunakan dalam pemrograman basis data

Peta<String, dinamis> toMap() => {


"id" : id,
"jumlah" : jumlah,
"tanggal" : tanggal.toString(),
"kategori" : kategori, };

• kolom - Variabel statis yang digunakan untuk mewakili bidang basis data.

• Masukkan dan simpan kode berikut ke dalam file Expense.dart.

impor 'paket:intl/intl.dart';

kelas Pengeluaran
{ final int id;
jumlah ganda akhir;
tanggal DateTime akhir;
kategori String terakhir;

String get formattedDate { var


formatter = new DateFormat('yyyy-MM-dd'); return
formatter.format(this.date);
}

kolom akhir statis = ['id', 'jumlah', 'tanggal', 'kategori'];

158
Machine Translated by Google

Berdebar

Pengeluaran(ini.id, ini.jumlah, ini.tanggal, ini.kategori);

biaya pabrik.fromMap(Map<String, dynamic> data) { return


Expense( data['id'], data['amount'],

DateTime.parse(data['date']),
data['category'] );

Peta<String, dinamis> toMap() => {


"id" : id,
"jumlah" : jumlah,
"tanggal" : tanggal.toString(),
"kategori" : kategori, };

• Kode di atas sederhana dan cukup jelas.

• Tambahkan file baru, Database.dart untuk membuat kelas SQLiteDbProvider. Tujuan kelas SQLiteDbProvider
adalah sebagai berikut:

• Dapatkan semua biaya yang tersedia di database menggunakan metode getAllExpenses. Dia
akan digunakan untuk mencantumkan semua informasi pengeluaran pengguna.

Future<List<Expense>> getAllExpenses() async {


final db = menunggu basis data;

Daftar<Peta> hasil = await db.query("Pengeluaran", kolom:


Pengeluaran.kolom, orderBy: "date DESC");

Daftar<Pengeluaran> pengeluaran = new


Daftar(); results.forEach((result) { Pengeluaran
pengeluaran = Pengeluaran.dariPeta(hasil);
pengeluaran.tambahkan(pengeluaran); });

biaya pengembalian;
}

• Dapatkan informasi pengeluaran khusus berdasarkan identitas pengeluaran yang tersedia di database
menggunakan metode getExpenseById. Ini akan digunakan untuk menunjukkan informasi
pengeluaran tertentu kepada pengguna.

Future<Expense> getExpenseById(int id) async {


final db = menunggu basis data;

var result = await db.query("Biaya", di mana: "id = ", di manaArgs: [id]);

159
Machine Translated by Google

Berdebar

mengembalikan result.isNotEmpty ? Pengeluaran.dariPeta(hasil.pertama) : Null;


}

• Dapatkan total pengeluaran pengguna menggunakan metode getTotalExpense. Boleh jadi


digunakan untuk menunjukkan total pengeluaran saat ini kepada pengguna.

Future<double> getTotalExpense() async {


final db = menunggu basis data;

Daftar<Peta> daftar = await db.rawQuery("Pilih SUM(jumlah) sebagai jumlah


dari biaya");

mengembalikan daftar.isNotEmpty ? daftar[0]["jumlah"] : Nol;


}

• Menambahkan informasi pengeluaran baru ke dalam database menggunakan metode insert. Itu akan
digunakan untuk menambahkan entri biaya baru ke dalam aplikasi oleh pengguna.

Future<Expense> insert(Biaya pengeluaran) async {


final db = menunggu basis data;

var maxIdResult = await db.rawQuery("SELECT MAX(id)+1 as last_inserted_id


FROM Expense");
var id = maxIdResult.first["last_inserted_id"];

var result = await db.rawInsert( "MASUKKAN


Ke Beban (id, jumlah, tanggal, kategori)"
"
NILAI (?, ?, ?, ?)", [id,
biaya.jumlah, biaya.tanggal.toString(), biaya.kategori] );

biaya pengembalian(id, biaya.jumlah, biaya.tanggal,


biaya.kategori); }

• Perbarui informasi pengeluaran yang ada menggunakan metode pembaruan. Ini akan digunakan untuk
mengedit dan memperbarui entri pengeluaran yang ada yang tersedia di sistem oleh pengguna.

perbarui (Produk biaya) async { final db =


menunggu basis data;

var result = await db.update("Expense", product.toMap(), where: "id = ?",


whereArgs: [product.id]);

mengembalikan hasil;
}

• Hapus informasi pengeluaran yang ada menggunakan metode hapus. Ini akan digunakan untuk
menghapus entri pengeluaran yang tersedia di sistem oleh pengguna.

hapus(int id) async {


final db = menunggu basis data;

160
Machine Translated by Google

Berdebar

db.delete("Biaya", di mana: "id = ?", di manaArgs: [id]);


}

• Kode lengkap kelas SQLiteDbProvider adalah sebagai berikut:

import 'dart:async'; impor


'panah: io'; impor 'paket:
jalur/jalur.dart';

import 'package:path_provider/path_provider.dart'; impor 'paket:


sqflite/sqflite.dart';

impor 'Biaya.dart';

kelas SQLiteDbProvider
{ SQLiteDbProvider._();

statis final SQLiteDbProvider db = SQLiteDbProvider._();

database statis _database;

Future<Database> dapatkan database async { if


(_database != null) return _database;

_database = menunggu initDB();


mengembalikan _database;
}

initDB() asinkron {
Direktori dokumenDirektori = menunggu getApplicationDocumentsDirectory(); Jalur string =
gabung(documentsDirectory.path, "ExpenseDB2.db"); kembali menunggu openDatabase( path,
versi: 1, onOpen: (db) {}, onCreate: (Database db, versi int) async {

await db.execute("CREATE TABLE Expense (" "id


INTEGER PRIMARY KEY," "amount REAL,"
"date TEXT," "category TEXT" ")");

await
db.execute( "INSERT INTO Expense ('id', 'amount', 'date', 'category') nilai (?, ?, ?, ?)",
[1, 1000, '2019-04-01 10 :00:00', "Makanan"]);

/*await
db.execute( "INSERT INTO Product ('id', 'name', 'description', 'price',
'gambar') nilai (?, ?, ?, ?, ?)",
[2, "Pixel", "Pixel adalah ponsel berfitur terbanyak yang pernah ada", 800,

161
Machine Translated by Google

Berdebar

"piksel.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[3, "Laptop", "Laptop adalah alat pengembangan paling produktif", 2000, "laptop.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[4, "Tablet", "Laptop adalah alat pengembangan paling produktif", 1500, "tablet.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[5, "Flashdisk", "iPhone adalah ponsel penata gaya", 100,
"pendrive.png"]);

await
db.execute( "MASUKKAN KE PRODUK ('id', 'nama', 'deskripsi', 'harga',
'gambar') nilai (?, ?, ?, ?, ?)",
[6, "Floppy Drive", "iPhone adalah ponsel stylist yang pernah ada", 20,
"floppy.png"]); */ });

Future<List<Expense>> getAllExpenses() async {


final db = menunggu basis data;

Daftar<Peta> hasil = await db.query("Pengeluaran", kolom: Pengeluaran.kolom, orderBy: "date


DESC");

Daftar<Pengeluaran> pengeluaran = new


Daftar(); results.forEach((result) { Pengeluaran
pengeluaran = Pengeluaran.dariPeta(hasil);
pengeluaran.tambahkan(pengeluaran); });

biaya pengembalian;
}

Future<Expense> getExpenseById(int id) async {


final db = menunggu basis data;

var result = await db.query("Biaya", di mana: "id = ", di manaArgs: [id]);

mengembalikan result.isNotEmpty ? Pengeluaran.dariPeta(hasil.pertama) : Null;


}

Future<double> getTotalExpense() async {


final db = menunggu basis data;

162
Machine Translated by Google

Berdebar

Daftar<Peta> daftar = await db.rawQuery("Pilih SUM(jumlah) sebagai jumlah dari pengeluaran");

mengembalikan daftar.isNotEmpty ? daftar[0]["jumlah"] : Nol;


}

Future<Expense> insert(Biaya pengeluaran) async {


final db = menunggu basis data;

var maxIdResult = await db.rawQuery("SELECT MAX(id)+1 as last_inserted_id FROM Expense");


var id = maxIdResult.first["last_inserted_id"];

var result = await db.rawInsert( "MASUKKAN


Ke Beban (id, jumlah, tanggal, kategori)"
"
NILAI (?, ?, ?, ?)", [id,
biaya.jumlah, biaya.tanggal.toString(), biaya.kategori]
);

biaya pengembalian(id, biaya.jumlah, biaya.tanggal, biaya.kategori);


}

perbarui (Produk biaya) async { final db =


menunggu basis data;

var result = await db.update("Expense", product.toMap(), where: "id = ?",


whereArgs: [product.id]);

mengembalikan hasil;
}

hapus (int id) async { final db


= menunggu basis data;

db.delete("Biaya", di mana: "id = ?", di mana Args: [id]);


}
}

• Di Sini,

• database adalah properti untuk mendapatkan objek SQLiteDbProvider.


• initDB adalah metode yang digunakan untuk memilih dan membuka database SQLite.

• Buat file baru, ExpenseListModel.dart untuk membuat ExpenseListModel. Tujuan dari model ini adalah untuk
menyimpan informasi lengkap tentang pengeluaran pengguna dalam memori dan memperbarui antarmuka
pengguna aplikasi setiap kali pengeluaran pengguna berubah dalam memori. Ini didasarkan pada kelas
Model dari paket scoped_model. Ini memiliki properti dan metode berikut:

• _items - daftar pengeluaran pribadi

• item - pengambil untuk _items sebagai UnmodifiableListView<Expense> untuk mencegah


perubahan tak terduga atau tidak disengaja pada daftar.

• totalExpense - pengambil Total biaya berdasarkan variabel item.

163
Machine Translated by Google

Berdebar

double get totalExpense { jumlah


ganda = 0,0; for(var i = 0; i <
_items.length; i++) { jumlah = jumlah +
_items[i].amount;
}

jumlah pengembalian;
}

• load - Digunakan untuk memuat pengeluaran lengkap dari database dan ke dalam variabel
_items. Itu juga memanggil notifyListeners untuk memperbarui UI.

void load()
{ Future<List<Expense>> list = SQLiteDbProvider.db.getAllExpenses();

list.then( (dbItems) { for(var


i = 0; i < dbItems.length; i++) {
_items.add(dbItems[i]); }

notifyListeners(); });

• byId - Digunakan untuk mendapatkan biaya tertentu dari variabel _items.

Pengeluaran menurutId(int
id) { for(var i = 0; i < _items.length; i++) { if(_items[i].id
== id) { return _items[i];

}
}

kembali nol;
}

• add - Digunakan untuk menambahkan item pengeluaran baru ke dalam variabel _items dan juga
ke dalam database. Itu juga memanggil notifyListeners untuk memperbarui UI.

void add(Item pengeluaran)


{ SQLiteDbProvider.db.insert(item).then((val) {
_items.add(val);

notifyListeners(); });

• add - Digunakan untuk menambahkan item pengeluaran baru ke dalam variabel _items dan juga ke
dalam database. Itu juga memanggil notifyListeners untuk memperbarui UI.

pembaruan batal (item Pengeluaran) {

bool ditemukan = salah;

164
Machine Translated by Google

Berdebar

for(var i = 0; i < _items.length; i++) { if(_items[i].id ==


item.id) { _items[i] = item; ditemukan = benar;
SQLiteDbProvider.db.update(item); merusak;

}
}

jika(ditemukan) notifyListeners();
}

• hapus - Digunakan untuk menghapus item pengeluaran yang ada di variabel _items juga
dari basis data. Itu juga memanggil notifyListeners untuk memperbarui UI.

batal hapus (item Pengeluaran) {

bool ditemukan = salah;

for(var i = 0; i < _items.length; i++) { if(_items[i].id ==


item.id) { ditemukan = true;
SQLiteDbProvider.db.delete(item.id);
_items.removeAt(i); merusak;

}
}

jika(ditemukan) notifyListeners();
}

• Kode lengkap kelas ExpenseListModel adalah sebagai berikut:

impor 'panah: koleksi'; import


'package:scoped_model/scoped_model.dart'; impor 'Biaya.dart';
impor 'Database.dart';

kelas ExpenseListModel memperluas Model {

ExpenseListModel() { this.load(); }

Daftar akhir<Biaya> _item = [];

UnmodifiableListView<Expense> dapatkan item =>


UnmodifiableListView(_items);

/*Future<double> dapatkan totalExpense


{ return SQLiteDbProvider.db.getTotalExpense(); }*/

double get totalExpense { jumlah


ganda = 0,0;

165
Machine Translated by Google

Berdebar

for(var i = 0; i < _items.length; i++) { jumlah =


jumlah + _items[i].amount;
}

jumlah pengembalian;
}

void load()
{ Future<List<Expense>> list =
SQLiteDbProvider.db.getAllExpenses();

list.then( (dbItems) { for(var


i = 0; i < dbItems.length; i++) {
_items.add(dbItems[i]);
}

notifyListeners(); });

Pengeluaran menurutId(int
id) { for(var i = 0; i < _items.length; i++)
{ if(_items[i].id == id) { return _items[i];

}
}

kembali nol;
}

void add(Item pengeluaran)


{ SQLiteDbProvider.db.insert(item).then((val) {
_items.add(val);

notifyListeners(); });

pembaruan batal (item Pengeluaran) {

bool ditemukan = salah;

for(var i = 0; i < _items.length; i++) { if(_items[i].id


== item.id) { _items[i] = item; ditemukan = benar;
SQLiteDbProvider.db.update(item); merusak;

}
}

jika(ditemukan) notifyListeners();
}

batal hapus (item Pengeluaran) {

166
Machine Translated by Google

Berdebar

bool ditemukan = salah;

for(var i = 0; i < _items.length; i++) { if(_items[i].id ==


item.id) { ditemukan = true;
SQLiteDbProvider.db.delete(item.id);
_items.removeAt(i); merusak;

}
}

jika(ditemukan) notifyListeners();
}
}

• Buka file main.dart. Impor kelas seperti yang ditentukan di bawah ini:

import 'package:flutter/material.dart'; import


'package:scoped_model/scoped_model.dart'; import
'ExpenseListModel.dart';

impor 'Biaya.dart';

• Tambahkan fungsi utama dan panggil runApp dengan meneruskan ScopedModel<ExpenseListModel>


widget.

void main()
{ biaya akhir = ExpenseListModel();

runApp(ScopedModel<ExpenseListModel>( model:
pengeluaran, anak: MyApp(), ));

• Di Sini,

• objek pengeluaran memuat semua informasi pengeluaran pengguna dari database.


Selain itu, saat aplikasi dibuka untuk pertama kali, aplikasi akan membuat database
yang diperlukan dengan tabel yang sesuai.

• ScopedModel memberikan informasi biaya selama seluruh siklus hidup aplikasi dan memastikan
pemeliharaan status aplikasi kapan saja. Ini memungkinkan kita untuk menggunakan
StatelessWidget alih-alih StatefulWidget.

• Buat MyApp sederhana menggunakan widget MaterialApp.

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

kembalikan
MaterialApp( judul:
'Biaya', tema: ThemeData(

167
Machine Translated by Google

Berdebar

primarySwatch: Colors.blue, ), home:


MyHomePage(judul: 'kalkulator biaya'), );

}
}

• Buat widget MyHomePage untuk menampilkan semua informasi pengeluaran pengguna beserta total
pengeluaran di bagian atas. Tombol floating di pojok kanan bawah akan digunakan untuk menambah
pengeluaran baru.

kelas MyHomePage extends StatelessWidget


{ MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title: Text(this.title), ),
body:

ScopedModelDescendant<ExpenseListModel>( builder:
(konteks, anak, pengeluaran) { return ListView.separated(

itemCount: pengeluaran.item == null ? 1 :


biaya.item.panjang + 1,
itemBuilder: (konteks, indeks) { if (indeks
== 0) { return ListTile( title: Text("Total
pengeluaran:
" +
pengeluaran.totalExpense.toString(),
gaya: TextStyle(fontSize: 24,fontWeight: FontWeight.bold), )

); } else
{ indeks = indeks - 1;
return Dismissible( key:
Key(expenses.items[index].id.toString()), onDismissed:
(direction) {
pengeluaran.hapus(pengeluaran.item[indeks]);

Scaffold.of(konteks).showSnackBar(SnackBar( konten:
Teks("Item dengan id, " +
pengeluaran.item[indeks].id.toString()
+
" diberhentikan")));
},
anak: ListTile( onTap:
()

{ Navigator.push( konteks,
MaterialPageRoute( pembangun: (konteks)
=> FormPage( id:
pengeluaran.item[indeks].id,

168
Machine Translated by Google

Berdebar

pengeluaran:
pengeluaran, )));
},
memimpin: Ikon(Icons.monetization_on), mengikuti:
Ikon(Icons.keyboard_arrow_right),

title: Text(expenses.items[index].category
+
":" +

pengeluaran.item[indeks].amount.toString() + " \nsbelanja


" +
untuk
pengeluaran.item[indeks].formattedDate, gaya:
TextStyle(fontSize: 18, fontStyle: FontStyle.italic),))); } }, separatorBuilder: (konteks, indeks)
{ return Divider(); }, ); }, ), floatingActionButton:
ScopedModelDescendant<ExpenseListModel>( pembangun: (konteks,
anak, pengeluaran) { return FloatingActionButton( onPressed: () {

Navigator.push( konteks,
MaterialPageRoute( pembangun:
(konteks) => ScopedModelDescendant<ExpenseListModel>(
pembangun: (konteks, turunan, pengeluaran)
{ return FormPage( id: 0,

pengeluaran:
pengeluaran, ); }))); //
pengeluaran.tambahkan(Pengeluaran
baru( 2, 1000, DateTime.parse('2019-04-01
11:00:00'), //
'Makanan'));
// cetak(pengeluaran.barang.panjang); },
keterangan alat: 'Kenaikan', anak:
Ikon(Ikon.tambahkan), ); }));

}
}

• Di Sini,

• ScopedModelDescendant digunakan untuk meneruskan model pengeluaran ke ListView dan


Widget FloatingActionButton.

169
Machine Translated by Google

Berdebar

• Widget ListView.separated dan ListTile digunakan untuk membuat daftar informasi pengeluaran.

• Widget yang dapat ditutup digunakan untuk menghapus entri pengeluaran menggunakan gerakan menggesek.

• Navigator digunakan untuk membuka antarmuka edit entri pengeluaran. Ini dapat diaktifkan oleh
mengetuk entri pengeluaran.

• Membuat widget FormPage. Tujuan widget FormPage adalah untuk menambah atau memperbarui entri
pengeluaran. Ini menangani validasi entri biaya juga.

kelas FormPage memperluas StatefulWidget {


FormPage({Key key, this.id, this.expenses}) : super(key: key);

int terakhir id;


biaya ExpenseListModel akhir;

@mengesampingkan

_FormPageState createState() => _FormPageState(id: id, pengeluaran:


pengeluaran); }

kelas _FormPageState memperluas Status<FormPage> {


_FormPageState({Kunci kunci, this.id, this.expenses});

int terakhir id;


biaya ExpenseListModel akhir;

scaffoldKey akhir = GlobalKey<ScaffoldState>(); final formKey


= GlobalKey<FormState>();

jumlah_ganda;
DateTime _date;
String _kategori;

batal _kirim() {
bentuk akhir = formKey.currentState;

if (form.validate())
{ form.save();

jika (ini.id == 0)
pengeluaran.tambahkan(Pengeluaran(0, _jumlah, _tanggal,
_kategori)); lainnya pengeluaran.update(Pengeluaran(ini.id, _jumlah,
_tanggal, _kategori));

Navigator.pop(konteks);
}
}

@mengesampingkan

Pembuatan widget(konteks BuildContext)


{ return Scaffold(
key: scaffoldKey,
appBar: AppBar( title:
Text('Masukkan detail pengeluaran'),

170
Machine Translated by Google

Berdebar

),
body:
Padding( padding: const EdgeInsets.all(16.0),
anak: Form( kunci: formKey, anak: Kolom( anak:
[ TextFormField( style: TextStyle(fontSize:
22), dekorasi: const InputDecoration( icon:
const Ikon(Icons.monetization_on),
labelText: 'Jumlah', labelStyle:
TextStyle(fontSize:

18)),
validator: (val) {
pola pola = r'^[1-9]\d*(\.\d+)?$'; RegExp regex = new
RegExp(pola); if (!regex.hasMatch(val)) return
'Masukkan nomor yang valid'; kalau tidak

kembali nol;
},
Nilai awal:
id == 0 ? '' : pengeluaran.byId(id).amount.toString(), onSaved:
(val) => _amount = double.parse(val), ), TextFormField( style:
TextStyle(fontSize: 22), dekorasi: const InputDecoration(

icon: const Icon(Icons.calendar_today), hintText:


'Masukkan tanggal', labelText: 'Tanggal', labelStyle:
TextStyle(fontSize: 18), ), validator: (val) {

Pola pola = r'^((?:19|


20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1- 9]| [12][0-9]|3[01])$';

RegExp regex = new RegExp(pola); jika (!


regex.hasMatch(val))
return 'Masukkan tanggal yang valid';
selain itu kembalikan null;

},
onSaved: (val) => _date = DateTime.parse(val), initialValue:
id == 0 ? '' pengeluaran.byId(id).formattedDate,
: keyboardType:
TextInputType.datetime, ), TextFormField( style: TextStyle(fontSize: 22), dekorasi:
const InputDecoration( icon: const Icon(Icons.category),
labelText:

'Kategori', labelStyle: TextStyle(fontSize: 18)), onSaved: (val)


=> _category = val, initialValue: id == 0 ? ''

: pengeluaran.byId(id).category.toString(),

171
Machine Translated by Google

Berdebar

),

RaisedButton( onPressed:
_kirim, anak: Teks
baru('Kirim'), ), ], ), ), ), );

}
}

• Di Sini,

• TextFormField digunakan untuk membuat entri formulir.

• properti validator dari TextFormField digunakan untuk memvalidasi elemen form bersama dengan
Pola RegEx.

• Fungsi _submit digunakan bersama dengan objek pengeluaran untuk menambah atau memperbarui
pengeluaran ke dalam database.

• Kode lengkap file main.dart adalah sebagai berikut:

import 'package:flutter/material.dart'; import


'package:scoped_model/scoped_model.dart'; import
'ExpenseListModel.dart';

impor 'Biaya.dart';

batal main() {
pengeluaran akhir = ExpenseListModel();

runApp(ScopedModel<ExpenseListModel>( model:
pengeluaran, anak: MyApp(), ));

class MyApp extends StatelessWidget { // Widget


ini adalah root dari aplikasi Anda. @override Widget
build(Konteks BuildContext) {

return MaterialApp( title:


'Expense', theme:

ThemeData( primarySwatch:
Colors.blue, ), home: MyHomePage(title:
'Expense calculator'), );

}
}

kelas MyHomePage memperluas StatelessWidget {

172
Machine Translated by Google

Berdebar

MyHomePage({Key key, this.title}) : super(key: key);

judul String terakhir;

@override
Widget build(BuildContext context) { return
Scaffold( appBar: AppBar( title: Text(this.title), ),
body:

ScopedModelDescendant<ExpenseListModel>( builder:
(konteks, anak, pengeluaran) { return ListView.separated(

itemCount: pengeluaran.item == null ? 1 :


biaya.item.panjang + 1,
itemBuilder: (konteks, indeks) { if (indeks
== 0) { return ListTile( title: Text("Total
pengeluaran:
" +
pengeluaran.totalExpense.toString(),
gaya: TextStyle(fontSize: 24,fontWeight: FontWeight.bold), )

); } else
{ indeks = indeks - 1;
return Dismissible( key:
Key(expenses.items[index].id.toString()), onDismissed:
(direction) {
pengeluaran.hapus(pengeluaran.item[indeks]);

Scaffold.of(konteks).showSnackBar(SnackBar( konten:
Teks("Item dengan id, " +
pengeluaran.item[indeks].id.toString() + "
diberhentikan")));
},
anak: ListTile( onTap:
()

{ Navigator.push( konteks,
MaterialPageRoute( pembangun: (konteks) => FormPage(
id: biaya.item[indeks].id,
pengeluaran:
pengeluaran, )));
},
memimpin: Ikon(Icons.monetization_on), mengikuti:
Ikon(Icons.keyboard_arrow_right), judul:
Teks(pengeluaran.item[indeks].kategori +
": " +
pengeluaran.item[indeks].amount.toString() + " \nsbelanja
" +
pengeluaran.item[indeks].formattedDate, gaya:

TextStyle(fontSize: 18, fontStyle: FontStyle.italic),)));

} },
separatorBuilder: (konteks, indeks) {

173
Machine Translated by Google

Berdebar

kembali
Pembagi(); }, ); }, ),
floatingActionButton:

ScopedModelDescendant<ExpenseListModel>( pembangun: (konteks, turunan,


pengeluaran) { return FloatingActionButton( onPressed: () {

Navigator.push( konteks,
MaterialPageRoute( pembangun: (konteks) =>
ScopedModelDescendant<ExpenseListModel>( pembangun:
(konteks, turunan, pengeluaran) { return
FormPage( id: 0,

pengeluaran:
pengeluaran, ); }))); //

pengeluaran.tambahkan(Pengeluaran baru( //
2, 1000,11:00:00'),
DateTime.parse('2019-04-01
'Makanan'));
// cetak(pengeluaran.barang.panjang); },
keterangan alat: 'Kenaikan', anak:
Ikon(Ikon.tambahkan), ); }));

}
}

kelas FormPage memperluas StatefulWidget {


FormPage({Key key, this.id, this.expenses}) : super(key: key);

int terakhir id;


biaya ExpenseListModel akhir;

@mengesampingkan

_FormPageState createState() => _FormPageState(id: id, pengeluaran:


pengeluaran); }

kelas _FormPageState memperluas Status<FormPage> {


_FormPageState({Kunci kunci, this.id, this.expenses});

int terakhir id;


biaya ExpenseListModel akhir;

scaffoldKey akhir = GlobalKey<ScaffoldState>(); final formKey


= GlobalKey<FormState>();

jumlah_ganda;
DateTime _date;
String _kategori;

174
Machine Translated by Google

Berdebar

batal _kirim() {
bentuk akhir = formKey.currentState;

if (form.validate())
{ form.save();

jika (ini.id == 0)
pengeluaran.tambahkan(Pengeluaran(0, _jumlah, _tanggal,
_kategori)); lainnya pengeluaran.update(Pengeluaran(ini.id, _jumlah,
_tanggal, _kategori));

Navigator.pop(konteks);
}
}

@mengesampingkan

Pembuatan widget(konteks BuildContext)


{ return Scaffold(
key: scaffoldKey,
appBar: AppBar( title:
Text('Masukkan detail pengeluaran'), ), body:
Padding( padding: const EdgeInsets.all(16.0),
child: Form( key: formKey, child: Column( children:
[ TextFormField( style: TextStyle(fontSize: 22),
dekorasi: const InputDecoration( icon: const
Icon(Icons.monetization_on), labelText:
'Jumlah', labelStyle: TextStyle(fontSize:

18)),
validator: (val) {
pola pola = r'^[1-9]\d*(\.\d+)?$'; RegExp regex = new
RegExp(pola); if (!regex.hasMatch(val)) return
'Masukkan nomor yang valid'; kalau tidak

kembali nol;
},
Nilai awal:
id == 0 ? '' : pengeluaran.byId(id).amount.toString(), onSaved:
(val) => _amount = double.parse(val), ), TextFormField( style:
TextStyle(fontSize: 22), dekorasi: const InputDecoration(

icon: const Icon(Icons.calendar_today), hintText:


'Masukkan tanggal', labelText: 'Tanggal', labelStyle:
TextStyle(fontSize: 18), ), validator: (val) {

175
Machine Translated by Google

Berdebar

Pola pola = r'^((?:19|


20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1- 9]| [12][0-9]|3[01])$';

RegExp regex = new RegExp(pola); jika (!


regex.hasMatch(val))
return 'Masukkan tanggal yang valid';
selain itu kembalikan null;

},
onSaved: (val) => _date = DateTime.parse(val), initialValue:
id == 0 ? '' pengeluaran.byId(id).formattedDate,
: keyboardType:
TextInputType.datetime, ), TextFormField( style: TextStyle(fontSize: 22), dekorasi:
const InputDecoration( icon: const Icon(Icons.category),
labelText:

'Kategori', labelStyle: TextStyle(fontSize: 18)), onSaved: (val) =>


_category = val, initialValue: id == 0 ? ''

: pengeluaran.byId(id).category.toString(),
),

RaisedButton( onPressed:
_kirim, anak: Teks
baru('Kirim'), ), ], ), ), ), );

}
}

• Sekarang, jalankan aplikasi.

• Tambahkan pengeluaran baru menggunakan tombol mengambang.

• Edit pengeluaran yang ada dengan mengetuk entri pengeluaran

• Hapus pengeluaran yang ada dengan menggeser entri pengeluaran ke salah satu arah.

176
Machine Translated by Google

Berdebar

Beberapa screen shot dari aplikasi ini adalah sebagai berikut:

177
Machine Translated by Google

Berdebar

178
Machine Translated by Google

Berdebar

179
Machine Translated by Google

21. Flutter – Kesimpulan Berdebar

Kerangka kerja Flutter melakukan pekerjaan yang hebat dengan menyediakan kerangka kerja yang sangat baik untuk
membangun aplikasi seluler dengan cara yang benar-benar mandiri platform. Dengan memberikan kemudahan dalam proses
pengembangan, kinerja tinggi dalam aplikasi seluler yang dihasilkan, antarmuka pengguna yang kaya dan relevan untuk platform
Android dan iOS, framework Flutter pasti akan memungkinkan banyak pengembang baru untuk mengembangkan aplikasi seluler
berkinerja tinggi dan penuh fitur di tidak lama lagi.

180

Anda mungkin juga menyukai