Created with to build something
Version: 5.0.0
cover-getx-library-yang-memudahkan-developer-flutter

Codding

GetX - Library Yang Memudahkan Developer Flutter

GetX merupakan library yang memuat fungsi state manager, navigation manager dan depedencies manager yang sangat memudahkan pembuatan aplikasi flutter.

Feb 22, 2021

Dalam perjalanan saya menggunakan flutter untuk mengembangkan aplikasi mobile, ya memang flutter terkadang cenderung lebih sulit untuk dikembangkan karena bahasa yang bisa tergolong masih baru. Ok, itu adalah hal yang biasa bagi saya, tapi dalam studi kasus tertentu saya masih belum menemukan library state management yang cocok untuk pengembangan aplikasi saya. Mungkin sebagai contohnya seperti bloc_library yang pernah saya bahas sebelumnya mengenai tutorial awal menggunakan bloc library pada flutter yang dirilis pada tanggal 21 oktober 2020.

Pada kondisi tertentu saya perlu menampilkan sebuah snackbar yang digunakan untuk menampilkan secarik pesan kesalahan, ketimbang saya menggunakan dialog untuk merusak UI saya lebih prefer menggunakan snackbar untuk menampilkan pesan kesalahan. Akan tetapi ada masalah saat mengimplementasikan hal ini, saya perlu menambahkan sebuah bloc listener untuk melihat apakah ada error atau tidak mungkin kodenya bisa dilihat sebagai berikut :

child: BlocListener<LoginBloc, LoginState>(
  listener: (context, state) {
    if (state.error.status == true) {
      Scaffold.of(context).showSnackBar(SnackBar(
        elevation: 6.0,
        behavior: SnackBarBehavior.floating,
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(state.error.value),
            SizedBox(
              child: state.error.detail != null
                  ? Text(state.error.detail)
                  : null,
            )
          ],
        ),
      ));
      context.read<LoginBloc>().add(LoginErrorHasRetrive());
      // context.bloc<LoginBloc>().add(LoginErrorHasRetrive());
    } else if (state.isAuthenticated == true) {
      Scaffold.of(context).showSnackBar(SnackBar(
          content: Text(
              "Login berhasil, sedang memproses autentikasi lokal")));
      context.read<LoginBloc>().add(LoginSuccessHasRetrieve());
      context.read<AuthenticationBloc>().add(AuthenticationCheck());
      // context.bloc<LoginBloc>().add(LoginSuccessHasRetrieve());
      // context.bloc<AuthenticationBloc>().add(AuthenticationCheck());
    }
  },

Untuk ku itu adalah jalur paling ribet dalam menampilkan snackbar dengan menggunakan bloc_library apalagi jika ingin berpindah halaman, sebagai akhirnya saya memahami bahwa harusnya saya tidak mengimplementasikan hal tersebut disini setelah membaca pertanyaan dari stackoverflow mengenai menempatkan buildcontext di bloc.

Mencoba GetX

Setelah beberapa teman baik yang ada di sosmed ataupun facebook group ramai membincangkan mengenai getx, tadi pagi saya mencoba untuk menggunakan GetX untuk mengetahui seberapa bahagianya saya setelah mencoba library yang satu ini mengingat i have a lot thing todo to make a simple feature on bloc_library.

Mencoba membuka package.yaml dan menambahkan ini ke dalam project baru flutter untuk mencoba getx.

dependencies:
  get: ^3.25.4

Jalannya flutter pub get atau simpan saja file tersebut dan biarkan IDE yang bekerja untuk mendownload dependencies tersebut.

Dimulai dari routing

Pada dependencies getx terdapat fitur bernama route management yang dimana kamu dapat mengatur rute dari setiap halaman yang akan dibuat pada project flutter, secara default saya tidak komplain terhadap routing bawaan flutter karena memang pada dasarnya sistem routing pada flutter tergolong cukup mudah tetapi dalam satu kondisi yaitu anda mendeklarasikan route pada sebuah file.

Mari kita mulai satu hal perbedaan paling mencolok pada sistem routing pada getx.

Navigate to direct class

Di kalimat akhir saya menyebutkan bahwa sistem routing pada flutter akan lebih mudah ketika routenya sudah di deklarasikan, akan tetapi jika routenya belum di deklarasikan atau bisa di istilahkan sebagai navigasi langsung ke class view ini menjadi hal yang lumayan repot apalagi view tersebut adalah view pendukung dari view sebelumnya.

// Default Flutter navigator
Navigator.of(context).push(
  context,
  MaterialPageRoute(
    builder: (BuildContext context) {
      return HomePage();
    },
  ),
);

// Get using Flutter syntax without needing context
navigator.push(
  MaterialPageRoute(
    builder: (_) {
      return HomePage();
    },
  ),
);

// Get syntax (It is much better, but you have the right to disagree)
Get.to(HomePage());

Jika anda disuruh untuk memilih bagaimana yang terbaik bagi kamu, mungkin kamu akan memilih cara ketiga dibanding kedua cara sebelumnya yang memilih syntax yang lumayan panjang. Mungkin disini saya tidak bisa mengatakan bahwa ini adalah hal yang relevan untuk mengganti sistem routing flutter dengan menggunakan getx tapi kamu bisa melihatnya nanti di bagian selanjutnya.

Navigate to named route

Pada bagian ini sebenarnya tidak ada yang spesial dikarenakan fungsinya masih sama dengan routing pada flutter, sebagai catatan saya menggunakan cara ini untuk bernavigasi pada project flutter yang nantinya saya buat.

import 'package:bbd_client_manager/pages/example/example.dart';
import 'package:bbd_client_manager/pages/example/example_2.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/example2',
      getPages: [
        GetPage(name: '/example', page: () => MyHomePage()),
        GetPage(name: '/example2', page: () => Example2())
      ],
    )
  );
}

Dengan cara tersebut kamu dapat melakukan navigasi dengan menggunakan method toNamed(), offNamed(), offAllNamed(). Cara ini sebenarnya mirip dengan navigasi bawaan flutter, hanya saja beberapa kemampuan seperti query name bisa kamu lakukan tanpa mengirim object ke route yang dituju.

Get.toNamed('/example?hello=world')

Nah jika kamu mengakses route tersebut dengan menggunakan query, kamu bisa mengambil querynya baik direct pada widget view, BLoC, ataupun controller dengan cara berikut.

print(Get.parameters['hello']);

Selain query kamu juga dapat menambahkan parameter tambahan pada daftar routing, mungkin tidak seperti routing bawaan flutter kamu tidak perlu menambahkan property baru pada statelesswidget ataupun statefullwidget sehingga kamu hanya perlu mengambil value parameter melalui cara sebelumnya.

import 'package:bbd_client_manager/pages/example/example.dart';
import 'package:bbd_client_manager/pages/example/example_2.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/example2',
      getPages: [
        GetPage(name: '/example/:hello', page: () => MyHomePage()),
        GetPage(name: '/example2', page: () => Example2())
      ],
    )
  );
}

Sebenarnya ada fitur lain seperti middleware, custom transisition route dan nested navigation, kamu bisa melihat dokumentasi lengkapnya pada tautan berikut.

State Management

Mari kita mulai ke bagian tersulit, state management merupakan hal tersulit dari sebagian pengembangan aplikasi baik pada platform desktop dan platform mobile. Di desktop mungkin ini adalah hal yang bisa anda tinggalkan atau lewati terlebih dahulu, namun di mobile karena keterbatasan resources dari setiap device ataupun lain sebagainya pemilihan state management adalah suatu hal yang terpenting.

Di mobx setidaknya ada dua jenis state management dimana keduanya pun dapat kamu gabungkan sesuai dengan apa yang kamu butuhkan untuk aplikasi mu, sedikit tidaknya kamu perlu tau hal ini.

Reactive State Manager

Reactive state manager merupakan salah satu state manager pada getx yang memiliki fungsionalitas yang lebih simple penggunaannya, karena dengan menggunakan ini kamu tidak perlu lagi membuat StreamController maupun StreamBuilder untuk mengakses state yang sudah kamu buat.

Saya membuat sedikit code untuk mengetahui seberapa mudahnya menggunakan reactive state manager.

import 'dart:convert';
import 'package:bbd_client_manager/controllers/Authentication/AuthController.dart';
import 'package:bbd_client_manager/services/Authentication/AuthHttp.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/state_manager.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AuthInitController extends GetxController {
  var status = 'initialize'.obs;
  final AuthController authController = Get.put(AuthController());
  @override
  void onInit() {
    super.onInit();
    checkAuthState();
  }
  void checkAuthState() async {
    final prefs = await SharedPreferences.getInstance();
    final data = prefs.getString('auth'); //to store token
    if (data != null) {
      checkAuthSession();
    } else {
      Get.offAllNamed('/login');
    }
  }
  void checkAuthSession() async {
    final prefs = await SharedPreferences.getInstance();
    final localAuth = prefs.getString('auth');
    final dynamic auth = jsonDecode(localAuth);
    try {
      await AuthHttp().checkSession(auth['token']);
      Get.offAllNamed('/dashboard');
    } on DioError catch (err) {
      if (err.type == DioErrorType.RESPONSE) {
        if (err.response.statusCode == 401) {
          authController.onLogout();
        } else {
          Get.offAllNamed('/dashboard');
        }
      } else {
        Get.offAllNamed('/dashboard');
        Get.rawSnackbar(
            title: 'Offline Mode',
            message:
                'Anda memasuki mode offline, anda tidak dapat melakukan perubahan apapun pada aplikasi',
            backgroundColor: Colors.red[600],
            icon: Icon(Icons.warning, color: Colors.white));
      }
    }
  }
}

Pada kasus ini saya membuat sebuah splash page yang digunakan untuk melakukan validasi apakah user sudah melakukan login ke dalam aplikasi atau belum, secara default saya dapat memasukkan proses tersebut langsung ke dalam sebuah page. Namun sayangnya jika hal itu dilakukan maka kemungkinan kode menjadi tidak rapi adalah hal yang sudah pasti terjadi, sebenarnya jika anda lebih teliti lagi cara ini lebih anda bisa melakukan hal yang sama dengan menggunakan bloc_library dengan menggunakan cubit hanya saja anda tidak mungkin bisa mengimpementasikan snackbar tanpa BuildContext.

Karena saya menggunakan reactive state manager untuk menangani ini dan meletakkan proses tersebut di controller, maka kode yang dihasilkan untuk membuat halaman akan menjadi seperti ini.

import 'package:bbd_client_manager/controllers/Authentication/InitController.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class IndexPage extends StatelessWidget {
  final AuthInitController authInitController = Get.put(AuthInitController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          CircularProgressIndicator(),
          SizedBox(height: 16),
          Obx(() {
            if (authInitController.status.value == 'initialize') {
              return Text('Sedang mengecek sesi pengguna');
            } else if (authInitController.status.value == 'checkToken') {
              return Text('Sedang mengecek autentikasi pengguna');
            } else {
              return Text('Terjadi Kesalahan');
            }
          })
        ],
      ),
    ));
  }
}

Terlihat rapi dan jika ingin melakukan perubahan saya tidak perlu lagi mengubah keseluruhan isi pada file view, seperti yang bilang sebelumnya karena ini tidak menggunakan StreamBuilder maka untuk mengakses property pada controller maka kamu hanya perlu menggunakan Obx(() { return Widget }) sebagai provider yang membantu kamu untuk mengakses state.

Untuk lebih lanjut kamu bisa lihat pada dokumentasi state management getx.

Simple State Manager

Simple state manager merupakan state manager yang mungkin berada di level advance dimana mungkin kamu akan menghadapi hal ini, berbeda dengan reactive state manager dimana perubahan UI akan selalu terjadi ketika ada perubahan pada state. Ini mungkin terdengar seperti ah mungkin aku belum membutuhkannya, akan tetapi untuk kondisi tertentu mungkin kamu belum membutuhkan untuk memperbarui state pada UI sehingga jika state berubah maka UI tidak perlu untuk berubah.

Penggunaannya mungkin akan terlihat sama seperti sebelumnya, hanya saja kamu perlu menjalankan method update() diakhir method void dan GetBuilder untuk mengakses state pada controller.

Kamu bisa melihat cara tersebut pada dokumentasi getx state manager.

Tersedia Tool Basic

Setelah membahas dua fitur yang rasanya sangat wah ditambah satu fitur yang menemani kedua fitur sebelumnya berupa depedency management yang bisa kalian lihat contohnya berupa sebuah file controller, tidak puas rasanya kalau mengintip beberapa tool basic yang sudah disediakan oleh getx seperti :

  1. Internationalization
  2. Mengganti Tema Aplikasi
  3. GetConnect
  4. GetPage Middleware
  5. GetView
  6. GetWidget
  7. GetResponsiveView

Mungkin untuk membahas ketiga itu artikel ini mungkin akan terasa kepanjangan dan terlihat seperti menjiplak saja dari dokumentasi, jadi jika kamu tertarik untuk menggunakan ketujuh tool tersebut sebaiknya baca dokumentasinya lebih lanjut.

Very First Impression

Karena artikel ini dibuat sehari sebelum saya pertama kali mencoba getx, rasanya saya sudah memang benar - benar sangat bahagia sekali menggunakan getx daripada menggunakan depedency yang lain semacam bloc_library yang mungkin saja tidak relevan dengan getx.

Saya masih belum mengetahui dimana kelemahan dari depdency yang satu ini, terlebih memang dokumentasinya yang terkesan agak membingungkan jika anda langsung loncat ke level advance. Mungkin membaca api refference adalah solusi terbaiknya saat ini, ya meskipun tutorial menggunakan getx saat ini cenderung masih sedikit dan lumayan jarang orang tahu mengenai depedency ini.

Jika memungkinkan saya mungkin akan mencoba untuk membuat tutorial CRUD menggunakan getx, baik dengan metode menggunakan RestfullAPI atau local database layaknya hive atau sqflite.

Ingin Berkomentar ?

Gunakan fitur komentar dengan bijak demi keamanan dan kenyamanan anda saat berselancar di dunia maya ini, mungkin undang - undang atau peraturan dari sebagian wilayah akan menjerat aktivitas yang ada pada kolom komentar.