Flutterize : Pengenalan Class pada Dart

Flutterize : Pengenalan Class pada Dart

Halo teman teman, pada artikel kali ini kita akan membahas mengenai pengenalan class pada Dart.

Class adalah sebuah blueprint, class bertugas menampung method-method dan variabel variabel terkait. Contohnya tentang pembuatan skema untuk membuat sebuah bangunan. Bangunan adalah objek dan skema adalah cetak biru (class). Objek sendiri merupakan sebuah variabel, yang merupakan representasi atau perwujudan dari class. 

Dalam penulisan nama class harus diawali dengan huruf kapital. Untuk membuat private variable atau method yang ada di dalam class tersebut adalah dengan cara menambahkan prefix ‘_’ di bagian depan nama variable atau method terkait.

Salah satu anggota class yang sering dipakai adalah constructor. Constructor merupakan sebuah method dimana kita bisa memberi nilai awal untuk class variable. Constructor akan langsung dieksekusi ketika sebuah objek dibuat.

Aturan constructor :

  1. Nama constructor harus sama dengan nama class.
  2. constructor tidak memiliki return value.

Berikut adalah contoh pembuatan class pada bahasa Dart.

void main() {

/*
Pembuatan objek john dari class Person
*/
  var john = Person('john', 'wick');
/*
Pemanggilan method greeting dari objek john
*/
  print(john.greeting());
}

/*
Pembuatan class Person
*/
class Person {

/*
Deklarasi variable
*/
  String firstName;
  String lastName;
  final String _level = "A rank";
  
/*
Pembuatan constructor dari class Person
*/
  Person(this.firstName, this.lastName);
  
  String greeting(){
    return "Hello, ${_getFullName()}";
  }

  String _getFullName(){
    return "$firstName $lastName";
  }
}

Oke teman teman, sekian dulu artikel kali ini. Sampai jumpa di artikel berikutnya.

Flutterize : Pengenalan Method pada Dart

Flutterize : Pengenalan Method pada Dart

Halo teman teman, pada artikel kali ini kita akan membahas mengenai pengenalan method atau function pada Dart.

Method adalah sebuah blok kode yang terdapat di dalam body class. Method dapat memecah kode menjadi sub-sub kode, sehingga kita bisa membuat program lebih efisien. Method dapat eksekusi berkali-kali dan biasanya method dibuat untuk menyelesaikan sebuah masalah yang khusus.

Jenis Method

Terdapat 2 jenis method di di dalam bahasa Dart. Method void dan non – void.

1. Method Void

Method void adalah method yang tidak mengembalikan nilai apapun setelah dieksekusi. Artinya, hanya melakukan sebuah proses.

2. Method Non – Void

Method non – void adalah method yang mengembalikan suatu nilai setelah dieksekusi.

Cara Penulisan

Ada beberapa cara penulisan method di dalam bahasa Dart. 

1. Penulisan method secara dinamis.

addOperation(int x, int y){
  return x + y;
}

addOperation(int x, int y){
  print(x + y);
}

/* 
Dart akan mendeteksi secara otomatis. Method yang memiliki return maka akan dianggap sebagai method non - void.
/*

2. Penulisan method void.

void addOperation(int x, int y){
  print(x + y);
}

/*
Urutan penulisannya adalah yang pertama keyword void nya. Yang kedua nama methodnya. Yang ketiga bagian paramaternya. Dan yang terakhir bagian isi blok kode nya. 
/*

3. Penulisan method non – void.

int addOperation(int x, int y){
  return x + y;
}

/*
Urutan penulisannya adalah yang pertama tipe data nilai yang akan dikembalikan. Yang kedua nama methodnya. Yang ketiga bagian parameternya. Dan yang terakhir bagian isi blok kode nya.
*/

Oke teman teman, sekian dulu artikel kali ini. Sampai jumpa di artikel berikutnya.

Flutterize : Pengenalan Variable pada Dart

Flutterize : Pengenalan Variable pada Dart

Halo teman teman, pada artikel kali ini kita akan membahas mengenai pengenalan variabel pada Dart.

Variabel adalah tempat penampungan data pada program yang kita buat sesuai dengan tipe datanya. Variabel sendiri akan disimpan ke dalam memori ketika program dijalankan dan akan dihapus ketika program dihentikan.

Tipe data merupakan sebuah pengklasifikasian data berdasarkan jenis data tersebut. Ada banyak tipe data dalam flutter. Contohnya adalah String, tipe data yang menampung teks.

Tipe data dibagi menjadi 2 Jenis. Yaitu tipe data primitif dan non-primitif.

Tipe data primitif merupakan tipe data dasar yang tersedia secara langsung pada suatu bahasa pemrograman.

Beberapa tipe data pada Dart

1. Number

Contohnya adalah int dan double. Adalah tipe data yang merepresentasikan angka.

int age = 18;

2. Strings

Contohnya adalah String. Adalah tipe data yang merepresentasikan teks.

String name = "Faris";

3. Booleans

Contohnya adalah Boolean. Adalah tipe data yang merepresentasikan Boolean true dan false.

bool isMarried = false;

4. Lists

Contohnya adalah List. Adalah tipe data yang merepresentasikan banyak kumpulan data dengan tipe data yang ditentukan.

List<String> memberNameList = ["Faris", "Angga", "Budi"];

5. Maps

Contohnya adalah Map. Adalah tipe data yang merepresentasikan data dengan pasangan key dan value.

Map<String, dynamic> myIdentity = {
  "name" : "Faris",
  "age" : 18,
  "hobby" : "Membaca"
};

Penulisan variable pada Dart

Secara dinamis

Yaitu cara penulisan variable yang tidak mendefinisikan tipe datanya secara langsung. Tipe data ini akan dideteksi otomatis oleh Dart sesuai dengan tipe data dari isi variable tersebut.

var name = "Faris";

Secara eksplisit

Yaitu penulisan variable dengan tipe datanya, misalnya kita ingin membuat variable age yang harus bertipe angka/number.

int age = 18;

Final/const variable

Cara penulisan variabel yang digunakan untuk membuat sebuah data menjadi tidak bisa diubah lagi value nya.

final someFinalVariable = "This is final variable";
const someConstantVariable = "This is constant variable";

Oke teman teman, sekian dulu artikel kali ini. Sampai jumpa di artikel berikutnya.

Flutterize : Membuat Splash Screen di Flutter

Flutterize : Membuat Splash Screen di Flutter

Halo teman teman, pada artikel kali ini kita akan membahas mengenai pembuatan splash screen pada aplikasi yang dibuat dengan Flutter.

Splash screen sendiri adalah tampilan pertama ketika kita menjalankan sebuah aplikasi.

Contoh splash screen :

Contoh splash screen

Pertama, buat projectnya terlebih dahulu. Kita beri nama splash_app.

Create New Flutter Project

Lalu buat kelas Statefull untuk menampung tampilan splash screen.

class SplashScreen extends StatefulWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold();
  }
}

Jangan lupa untuk mengganti value dari parameter home pada MaterialApp yang ada pada kelas MyApp.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SplashScreen(),
    );
  }
}

Setelah itu, buat tampilan splash screen nya terlebih dahulu pada class _SplashScreenState.

    return Scaffold(
      backgroundColor: Colors.blue,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              Icons.map,
              color: Colors.white,
              size: 70,
            ),
            SizedBox(
              height: 10,
            ),
            Text(
              "Mappy",
              style: TextStyle(
                color: Colors.white,
                fontSize: 30,
                fontWeight: FontWeight.w700,
              ),
            ),
          ],
        ),
      ),
    );

Setelah itu, kita akan membuat method yang akan dijalankan ketika splash screen nya ditampilkan.

  void movingToNextScreen() {
    Timer(Duration(seconds: 3,), () {});
  }

Pada kode tersebuh, kita juga bisa mengatur berapa lama splash screen ditampilkan Sebelum dialihkan ke screen selanjutnya.

Panggil method tersebut pada body override method initState.

@override
  void initState() {
    super.initState();
    movingToNextScreen();
  }

Tambahkan HomeScreen untuk tampilan berikutnya.

import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(
          "Ini Home Screen",
        ),
      ),
    );
  }
}

Pada bagian callback dari Timer nya, kita berikan fungsi untuk berpindah ke halaman HomeScreen.

void movingToNextScreen() {
    Timer(
        Duration(
          seconds: 3,
        ), () {
      Navigator.pushReplacement(
          context,
          MaterialPageRoute(
            builder: (context) => HomeScreen(),
          ));
    });
  }

Setelah itu, kalian bisa langsung jalankan aplikasinya.

Oke teman teman, sekian dulu artikel kali ini. Sampai jumpa di artikel berikutnya.

See Ya’

Link Project : Github

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 4)

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 4)

Setelah pada artikel sebelumnya kita sudah bisa membuat operasi delete, selanjutnya kita akan membuat operasi update pada aplikasi yang kita buat sebelumnya.

Pertama, buat screen untuk form update. Beri nama class nya UpdateScreen.

Sehingga kodenya menjadi seperti ini.

class UpdateScreen extends StatefulWidget {
final String documentId;
final String task;
final String description;
const UpdateScreen({Key key, this.documentId, this.task, this.description}) : super(key: key);

@override
_UpdateScreenState createState() => _UpdateScreenState();
}

class _UpdateScreenState extends State<UpdateScreen> {
@override
Widget build(BuildContext context) {
return Scaffold();
}
}

Jangan lupa untuk menambahkan property pada class UpdateScreen untuk menampung kiriman data dari layar sebelumnya.

Tambahkan parameter onTap pada widget ListTile. Berikan code untuk berpindah screen ke UpdateScreen.

ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =&gt; UpdateScreen(
description: snapshot.data.documents[index]['task'],
documentId: snapshot.data.documents[index].documentID,
task: snapshot.data.documents[index]['task'],
),
));
},
title: Text(snapshot.data.documents[index]['task']),
subtitle: Text(snapshot.data.documents[index]['description']),
),

Selanjutnya, tambahkan property GlobalKey untuk FormState. Juga TextEdittingController untuk TextFormField title dan description.

final updateFormKey = GlobalKey<FormState&gt;();
TextEditingController titleTaskController = TextEditingController();
TextEditingController descTaskController = TextEditingController();

Lalu isi teks dari TextFormField nya dengan cara memanggil TextEdittingController nya pada override method initState().

@override
  void initState() {
    super.initState();
    titleTaskController.text = widget.task;
    descTaskController.text = widget.description;
  }

Selanjutnya, buat layout untuk tamnpilan UpdateScreen

    return Scaffold(
      appBar: AppBar(
        title: Text("Update Task"),
        leading: IconButton(
          onPressed: () =&gt; Navigator.pop(context),
          icon: Icon(Icons.arrow_back),
        ),
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(20),
        child: Form(
          autovalidateMode: AutovalidateMode.always,
          key: updateFormKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                "Task Name",
                style: TextStyle(
                  fontWeight: FontWeight.w600,
                ),
              ),
              SizedBox(
                height: 8,
              ),
              TextFormField(
                validator: (value) {
                  if (value.isEmpty || value.trim().length == 0) {
                    return "Task name cannot be empty";
                  }
                  return null;
                },
                controller: titleTaskController,
                style: TextStyle(
                  color: Colors.black,
                ),
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: "Update Task Name....",
                ),
              ),
              SizedBox(
                height: 12,
              ),
              Text(
                "Task Description",
                style: TextStyle(
                  fontWeight: FontWeight.w600,
                ),
              ),
              SizedBox(
                height: 8,
              ),
              TextFormField(
                controller: descTaskController,
                validator: (value) {
                  if (value.isEmpty || value.trim().length == 0) {
                    return "Task description cannot be empty";
                  }
                  return null;
                },
                style: TextStyle(
                  color: Colors.black,
                ),
                maxLines: 4,
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: "Update Task Description....",
                ),
              ),
              SizedBox(
                height: 24,
              ),
              FlatButton(
                minWidth: MediaQuery.of(context).size.width,
                padding: EdgeInsets.all(10),
                color: Colors.blue,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Text(
                  "Submit",
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20,
                  ),
                ),
                onPressed: () async {
                },
              ),
            ],
          ),
        ),
      ),
    );

Lalu tambahkan code proses update ketika tomboy submit di tekan.

if (updateFormKey.currentState.validate()) {
progressDialog(context).show();

Firestore firestore = Firestore.instance;

DocumentReference reference = firestore.document("todo/${widget.documentId}");
firestore.runTransaction((transaction) async {
DocumentSnapshot snapshot = await transaction.get(reference);

if (snapshot.exists){
transaction.update(reference, <String, dynamic>{
'task': titleTaskController.text.toString(),
'description': descTaskController.text.toString(),
}).then((value) {
progressDialog(context).hide();
successAlert("Success", "Success Insert Task", context);
}).catchError((error){
progressDialog(context).hide();
errorAlert("Failed", "Failed to Insert Task", context);
});
}

}).then((value) {
progressDialog(context).hide();
successAlert("Success", "Success Insert Task", context);
}).catchError((error){
progressDialog(context).hide();
errorAlert("Failed", "Failed to Insert Task", context);
});

} else {
errorAlert("Failed", "Please fill all the fields", context);
}

Untuk final aplikasi bisa kalian clone project di link GitHub dibawah.

See Ya’

Link Project : Github

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 3)

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 3)

Setelah pada artikel sebelumnya kita sudah bisa membuat operasi insert, selanjutnya kita akan membuat operasi delete pada aplikasi yang kita buat sebelumnya.

Pertama, jadikan Dismissible Widget sebagai parent widget dari ListTile. Berikan parameter key dengan isi documentID. Ganti warna background Container Widget dengan warns merah. Jangan lupa berikan callback onDismissed untuk handle widget ketika di swipe kesamping supaya melakukan proses delete pada Cloud Firestore.

Sehingga kodenya menjadi seperti ini.

return ListView.builder(
  itemCount: snapshot.data.documents.length,
  itemBuilder: (context, index) {
    return Dismissible(
      key: Key(snapshot.data.documents[index].documentID),
      background: Container(color: Colors.red,),
      onDismissed: (direction) async {},
      child: ListTile(
        title: Text(snapshot.data.documents[index]['task']),
        subtitle: Text(snapshot.data.documents[index]['description']),
      ),
    );
  },
);

Selanjutnya, berikan proses delete pada parameter onDismissed.

Firestore.instance.collection('todo').document(snapshot.data.documents[index].documentID).delete();

Sehingga kode menjadi seperti ini.

return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return Dismissible(
key: Key(snapshot.data.documents[index].documentID),
background: Container(color: Colors.red,),
onDismissed: (direction) async {
Firestore.instance.collection('todo').document(snapshot.data.documents[index].documentID).delete();
},
child: ListTile(
title: Text(snapshot.data.documents[index]['task']),
subtitle: Text(snapshot.data.documents[index]['description']),
),
);
},
);

Maka aplikasi nya akan menjadi seperti ini.

Untuk proses edit nya akan ada di artikel selanjutnya.

See Ya’

Link Project : Github

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 2)

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 2)

Setelah kemarin kita berhasil menampilkan list data dari database yang sudah dibuat di Cloud Firestore, pada postingan ini kita akan membuat operasi insert ke dalam database Cloud Firestore.

Jika belum melihat postingan sebelumnya, silahkan dilihat terlebih dahulu. Link disediakan di bawah.
Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 1)

Pertama, buat Floating Button di pojok kanan bawah untuk berpindah ke screen untuk insert data.

floatingActionButton: FloatingActionButton(
  child: Icon(Icons.add),
  onPressed: () {},
),

Kedua, buat class baru untuk menampung tampilan form insert.

class InsertScreen extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return InsertScreenState();
  }
}

class InsertScreenState extends State<InsertScreen>{
  @override
  Widget build(BuildContext context) {
    return Scaffold();
  }
}

Selanjutnya, buat App Bar. Sehingga kodenya menjadi seperti ini.

class InsertScreenState extends State<InsertScreen>{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Add New Task"),
        leading: IconButton(
          onPressed: () => Navigator.pop(context),
          icon: Icon(Icons.arrow_back),
        ),
      ),
    );
  }
}

Selanjutnya, buat form untuk memasukkan value yang akan di kirim ke database Cloud Firestore.

Buat controller untuk field nya terlebih dahulu.

TextEditingController titleTaskController = TextEditingController();
TextEditingController descTaskController = TextEditingController();

Setelah itu buat layoutnya.

body: SingleChildScrollView(
  padding: EdgeInsets.all(20),
  child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          "Task Name",
          style: TextStyle(
            fontWeight: FontWeight.w600,
          ),
        ),
        SizedBox(
          height: 8,
        ),
        TextFormField(
          validator: (value) {
            if (value.isEmpty || value.trim().length == 0) {
              return "Task name cannot be empty";
            }
            return null;
          },
          controller: titleTaskController,
          style: TextStyle(
            color: Colors.black,
          ),
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            hintText: "Insert Task Name....",
          ),
        ),
        SizedBox(
          height: 12,
        ),
        Text(
          "Task Description",
          style: TextStyle(
            fontWeight: FontWeight.w600,
          ),
        ),
        SizedBox(
          height: 8,
        ),
        TextFormField(
          controller: descTaskController,
          validator: (value) {
            if (value.isEmpty || value.trim().length == 0) {
              return "Task description cannot be empty";
            }
            return null;
          },
          style: TextStyle(
            color: Colors.black,
          ),
          maxLines: 4,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            hintText: "Insert Task Description....",
          ),
        ),
        SizedBox(
          height: 24,
        ),
        FlatButton(
          minWidth: MediaQuery.of(context).size.width,
          padding: EdgeInsets.all(10),
          color: Colors.blue,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          child: Text(
            "Submit",
            style: TextStyle(
              color: Colors.white,
              fontSize: 20,
            ),
          ),
          onPressed: () {
            if (insertFormKey.currentState.validate()){

            } else {

            }
          },
        ),
      ],
  ),
),

Jangan lupa memasukkan layout tersebut kedalam widget Form supaya bisa membuat validasi form. Sehingga kode menjadi seperti ini.

body: SingleChildScrollView(
  padding: EdgeInsets.all(20),
  child: Form(
    autovalidateMode: AutovalidateMode.always,
    key: insertFormKey,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          "Task Name",
          style: TextStyle(
            fontWeight: FontWeight.w600,
          ),
        ),
        SizedBox(
          height: 8,
        ),
        TextFormField(
          validator: (value) {
            if (value.isEmpty || value.trim().length == 0) {
              return "Task name cannot be empty";
            }
            return null;
          },
          controller: titleTaskController,
          style: TextStyle(
            color: Colors.black,
          ),
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            hintText: "Insert Task Name....",
          ),
        ),
        SizedBox(
          height: 12,
        ),
        Text(
          "Task Description",
          style: TextStyle(
            fontWeight: FontWeight.w600,
          ),
        ),
        SizedBox(
          height: 8,
        ),
        TextFormField(
          controller: descTaskController,
          validator: (value) {
            if (value.isEmpty || value.trim().length == 0) {
              return "Task description cannot be empty";
            }
            return null;
          },
          style: TextStyle(
            color: Colors.black,
          ),
          maxLines: 4,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            hintText: "Insert Task Description....",
          ),
        ),
        SizedBox(
          height: 24,
        ),
        FlatButton(
          minWidth: MediaQuery.of(context).size.width,
          padding: EdgeInsets.all(10),
          color: Colors.blue,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          child: Text(
            "Submit",
            style: TextStyle(
              color: Colors.white,
              fontSize: 20,
            ),
          ),
          onPressed: () async {},
        ),
      ],
    ),
  ),
),

Tambahkan juga key form nya.

final insertFormKey = GlobalKey<FormState>();

Setelah itu, tambahkan library rflutter_alert dan juga progress_dialog di pubspec.yaml.

rflutter_alert: any
progress_dialog: any

Buat layout untuk loading, success alert, dan juga error alertnya.

ProgressDialog progressDialog(BuildContext ctx) {
  ProgressDialog loadingDialog = ProgressDialog(
    ctx,
    type: ProgressDialogType.Normal,
    isDismissible: false,
  );
  loadingDialog.style(
    message: "Loading",
    progressWidget: Container(
      padding: EdgeInsets.all(8.0),
      child: CircularProgressIndicator(
        backgroundColor: Colors.blue,
      ),
    ),
    backgroundColor: Colors.white,
    elevation: 10.0,
    insetAnimCurve: Curves.easeInOut,
    messageTextStyle: TextStyle(
      color: Colors.blue,
    ),
  );
  return loadingDialog;
}

successAlert(String title, String subtitle, BuildContext ctx) {
  return Alert(
    context: ctx,
    title: title,
    desc: subtitle,
    type: AlertType.success,
    buttons: [
      DialogButton(
        onPressed: () {
          Navigator.pop(ctx);
        },
        child: Text(
          "Ok",
          style: TextStyle(color: Colors.white, fontSize: 20),
        ),
      ),
    ],
    style: AlertStyle(
      animationType: AnimationType.grow,
      isCloseButton: false,
      isOverlayTapDismiss: false,
      descStyle: TextStyle(fontWeight: FontWeight.bold),
      descTextAlign: TextAlign.center,
      animationDuration: Duration(milliseconds: 400),
      alertBorder: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
        side: BorderSide(
          color: Colors.grey,
        ),
      ),
      titleStyle: TextStyle(
        color: Colors.blue,
      ),
      alertAlignment: Alignment.center,
    ),
  ).show();
}

errorAlert(String title, String subtitle, BuildContext ctx) {
  return Alert(
    context: ctx,
    title: title,
    desc: subtitle,
    type: AlertType.warning,
    buttons: [
      DialogButton(
        onPressed: () => Navigator.pop(ctx),
        child: Text(
          "OK",
          style: TextStyle(color: Colors.white, fontSize: 20),
        ),
      ),
    ],
    style: AlertStyle(
      animationType: AnimationType.grow,
      isCloseButton: false,
      isOverlayTapDismiss: false,
      descStyle: TextStyle(fontWeight: FontWeight.bold),
      descTextAlign: TextAlign.center,
      animationDuration: Duration(milliseconds: 400),
      alertBorder: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10),
        side: BorderSide(
          color: Colors.grey,
        ),
      ),
      titleStyle: TextStyle(
        color: Colors.red,
      ),
      alertAlignment: Alignment.center,
    ),
  ).show();
}

Selanjutnya, buat proses insert dari form yang sudah kita buat tadi. Tempatkan proses nya ketika tombol submit di tekan.

if (insertFormKey.currentState.validate()){
  progressDialog(context).show();
  DocumentReference result = await Firestore.instance.collection('todo').add(<String, dynamic>{
    'task' : titleTaskController.text.toString(),
    'description' : descTaskController.text.toString(),
  });
  if (result.documentID != null){
    progressDialog(context).hide();
    successAlert("Success", "Success Insert Task", context);
  } else {
    progressDialog(context).hide();
    errorAlert("Failed", "Failed to Insert Task", context);
  }
} else {
  errorAlert("Failed", "Please fill all the fields", context);
}

Setelah itu tambahkan route dari MyHomePage menuju InsertScreen pada FloatingActionButton.

floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => InsertScreen(),
)),
),

Nah Setelah sampai sini, bisa dicoba. Namun list nya tidak akan berubah kecuali aplikasi di restart.

Solusinya adalah dengan merubah parent widget ListView dari FutureBuilder menjadi StreamBuilder. Berikut adalah kodenya.

body: StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('todo').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blue,
),
);
}
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data.documents[index]['task']),
subtitle: Text(snapshot.data.documents[index]['description']),
);
},
);
},
),

Maka aplikasi nya akan menjadi seperti ini.

Untuk proses edit, dan delete nya akan ada di artikel selanjutnya.

See Ya’

Link Project : Github

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 1)

Flutterize : Membuat Todo List App Menggunakan Flutter dan Cloud Firestore (PART 1)

Pada kesempatan kali ini, kita akan membuat aplikasi Todo List menggunakan Flutter dan Firebase Cloud Firestore. Khusus untuk post kali ini, kita akan membahas mengenai cara membaca data atau get data dari Firestore. Untuk proses Insert, Edit, dan Delete nya akan ada di post selanjutnya.

Sebelum lanjut pembuatan aplikasi nya, kita akan berkenalan dahulu dengan Cloud Firestore ini.

Cloud Firestore adalah database yang fleksibel dan skalabel untuk pengembangan seluler, web, dan server di Firebase dan Google Cloud Platform.

– Documentasi Firestore

Dengan kata lain, Firestore merupakan cloud database yang bermodelkan NoSQL. Firestore menyimpan data sebagai kumpulan dokumen. Sedangkan Realtime Database menyimpan data sebagai JSON. Cloud Firestore juga menampilkan kueri yang lebih kaya dan lebih cepat serta menskalakan lebih jauh daripada Realtime Database.

Menyiapkan Projek di Firebase

Siapkan akun Google di Firebase nya. Masuk ke Console.

Pertama, buat project di Firebase terlebih dahulu.

Selanjutnya, buat inisialisasi projeknya dan berikan konfigurasi dasar seperti dibawah.

Selanjutnya, kita akan di bawa ke dashboard dari console Firebase. Tambahkan projek sesuai dengan platform yang akan dibuat. Untuk kali ini, kita akan memilih platform android.

Karena kita akan membuat aplikasi android, maka kita pilih platformnya. Dilangkah pertama ini, masukkan nama package dan juga nama aplikasinya (optional). Untuk sementara, kode sertifikat SHA-1 nya di kosongkan.

Di step kedua, download file JSON yang telah di generate oleh Firebase. File ini akan disimpan di folder android/app/ .

Di step ketiga akan di beritahu untuk menambahkan Firebase SDK. (step ini akan di bahas selanjutnya).

Selesaikan pendaftaran aplikasi androidnya.

Inisialisasi Cloud Firestore

Selanjutnya, pilih Cloud Firestore yang ada di sidebar console, lalu pilih Buat database. Atur Firestore ke dalam metode pengujian. Lokasi server bisa disesuaikan dengan preferensi.

Instalasi Plugin

Beralih ke projek flutternya yang sudah dibuat menggunakan Android Studio atau Visual Studio Code. Tambahkan file google-services.json yang telah kita download ke direktori project flutter nya. Masukkan ke android/app/

Tambahkan dependency google services di direktori android/build.gradle.

dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.3.3'
    }

Pada direktori android/app/build.gradle apply plugin google services dan juga tambahkan dependency google services serta firebase core.

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.google.gms:google-services:4.3.3'
    implementation 'com.google.firebase:firebase-core:17.4.4'
}

Jangan lupa juga menambahkan setting untuk multi dex supaya tidak muncul error seperti ini.

Solusi nya adalah dengan mengatur multi dex menjadi enabled. Pengaturannya terdapat pada android/app/build.gradle

defaultConfig {
applicationId "com.quifar.todo_list_firestore"
minSdkVersion 16
targetSdkVersion 29
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.gms:google-services:4.3.3'
implementation 'com.google.firebase:firebase-core:17.4.4'
implementation 'com.android.support:multidex:1.0.3'
implementation "androidx.multidex:multidex:2.0.1"
}

Tambahkan dependency Flutter cloud_firestore dan juga firebase_core pada file pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.1
  cloud_firestore: ^0.13.5
  firebase_core: ^0.4.0+9

Selanjutnya pada teminal (sesuaikan dengan direktori project), ketikkan command dibawah.

flutter pub get

Selanjutnya, kita pindah ke Firestore di Console Firebase. Lalu pilih mulai koleksi. Isi nama koleksi sesuai dengan keinginan.

Lalu tambahkan dokumen pertamanya. Klik ID Otomatis untuk menggunakan id unik otomatis. Jangan lupa Tambahkan kolom beserta isinya untuk inisialisasi koleksi.

Kembali ke projek Flutternya. Bersihkan file lib/main.dart dari komentar supaya lebih rapih. Serta jadikan class _MyHomePageState menjadi seperti ini.

Coding

Selanjutnya tambahkan plugin cloud_firestore import

import 'package:cloud_firestore/cloud_firestore.dart';

pada parameter body kita akan menggunakan Widget FutureBuilder untuk mengambil data dari koleksi Firestore yang sudah kita buat. Parameter future nya diisikan code yang akan return hasil query dari Cloud Firestore.

body: FutureBuilder(
  future: Firestore.instance.collection('todo').getDocuments(),
),

Selanjutnya, tambahkan builder pada widget tersebut untuk membuat Loading CircleProgressIndicator dan juga ListView untuk menampung hasil query yang kita buat sebelumnya.

builder: (context, snapshot) {
  if (!snapshot.hasData) {
    return Center(
      child: CircularProgressIndicator(
        backgroundColor: Colors.blue,
      ),
    );
  }
},

Kode diatas akan mengatasi jika querynya belum atau tidak memiliki data maka akan ditampilkan Loading CircleProgressIndicator.

Selanjutnya, kita akan membuat kode yang akan mengatasi ketika query memiliki hasil atau data. Buat return menjadi ListView.builder seperti ini.

body: FutureBuilder(
  future: Firestore.instance.collection('todo').getDocuments(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return Center(
        child: CircularProgressIndicator(
          backgroundColor: Colors.blue,
        ),
      );
    }
    return ListView.builder();
  },
),

Lalu berikan parameter itemCount dan isi dengan panjang dari datanya.

return ListView.builder(
  itemCount: snapshot.data.documents.length,
);

Selanjutnya, kita buat layout dari ListView tersebut. Kita akan menggunakan widget ListTile.

return ListView.builder(
  itemCount: snapshot.data.documents.length,
  itemBuilder: (context, index) {
    return ListTile();
  },
);

Di dalam ListTile kita akan menampilkan kolom ‘title’ dan juga ‘description’.

return ListView.builder(
  itemCount: snapshot.data.documents.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(snapshot.data.documents[index]['task']),
      subtitle: Text(snapshot.data.documents[index]['description']),
    );
  },
);

Pada hasil akhir, kodenya akan menjadi seperti ini.

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

void main() async {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FutureBuilder(
future: Firestore.instance.collection('todo').getDocuments(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blue,
),
);
}
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data.documents[index]['task']),
subtitle: Text(snapshot.data.documents[index]['description']),
);
},
);
},
),
);
}
}

Hasil Akhir

Tampilan nya akan menjadi seperti ini.

Untuk proses insert, edit, dan delete nya akan ada di artikel selanjutnya.

See Ya’

Link Project : Github