HTTP Request Menggunakan Flutter

Di tutorial pintar-android.com kali ini kita akan belajar menampilkan list dengan data dari HTTP request menggunakan Flutter. HTTP request yang kita coba buat, akan menembak API yang dibuat dari data Firebase Realtime Database. API tersebut berisi data lirik lagu Jason Mraz yang berjudul “The Woman I Love”. Untuk yang mengikuti tutorial sebelumnya, pasti tahu kalau lagu yang sama juga dipakai untuk belajar membuat model menggunakan Flutter 😀

Mari kita mulai! Download kodingan dari tutorial sebelumnya di https://github.com/meidikawardana/instagram_list . Ekstrak file zip dari project tersebut, lalu rename folder hasil ekstrakan jadi: instagram_list . Buka folder tersebut di Visual Studio Code (VSCode), lalu tekan Ctrl+` (Control + tanda quote) di keyboard untuk membuka terminal di VSCode. lalu ketik di terminal:

flutter pub get

untuk download package flutter supaya project kita bisa jalan.

Sebelum kita menembak API pakai Flutter, kita perlu menyesuaikan sedikit kodingan kita supaya listview yang sudah ada bisa menampilkan data lebih efisien & mengurangi lag ketika di-scroll. Buka file lib/main.dart, lalu cari class InstagramCards. Ubah class InstagramCards sesuai kodingan dibawah ini. Hapus bagian yang dicoret, & tambahkan bagian yang berwarna hijau.

...

class InstagramCards extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    ...

    List<Widget> cards =
        new List.generate(3, (i) => new InstagramCard(instagramPost));

    return ListView(
      children: cards, /*<Widget>[
        InstagramCard()
      ],*/
    );

    return ListView.builder(
      itemBuilder: (BuildContext context, int index) {
        return InstagramCard(instagramPost);
      },
      itemCount: 3,
    );    
  }
}

Setelah itu, kita bisa mulai koding untuk menembak API firebase. Kita perlu menambahkan dulu library untuk menembak API, yaitu library http. Buka file pubspec.yaml, lalu tambahkan baris: http: ^0.12.0+2 di bagian dependencies seperti gambar berikut ini:

gambar  1 - menambahkan library http di pubspec.yaml

Lalu, masih di file main.dart, tambahkan import library http & tambahkan juga fungsi getPosts() untuk mendapatkan data dari API firebase realtime database. Di fungsi getPosts() inilah kita melakukan http request menggunakan Flutter.

...
import 'models/instagram_post.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() => runApp(AplikasiLikeInstagram());

Future<List<InstagramPost>> getPosts() async {
  final response =
      await http.get('https://instagram-list.firebaseio.com/posts.json');

  if (response.statusCode == 200) {
    final List<InstagramPost> postList = [];
    final Map<String, dynamic> postsJson = json.decode(response.body);

    postsJson.forEach((String id, dynamic data) {
      final InstagramPost product = InstagramPost(
        profilePicture: 'images/insta_profpic.jpg',
        username: 'meidika_wardana',
        picture: data['pic_url'],
        likeCount: int.parse(data['like_count']),
        text: data['text_'],
      );
      postList.add(product);
    });

    return postList;
  } else {
    throw Exception('Gagal menampilkan postingan');
  }
}

class InstagramCards extends StatefulWidget {
   ...

Kalau kita amati, ada beberapa hal yang menarik di fungsi getPosts() di atas. Fungsi getPosts(), biasanya kita sebut sebagai fungsi asynchronous (async) yang menunggu (await) suatu proses. Prosesnya untuk kasus ini adalah menembak API firebase di https://instagram-list.firebaseio.com/posts.json . Proses asynchronous ini, dilakukan di diluar proses utama aplikasi kita (main thread) karena jika dilakukan di main thread, proses async - await bisa memakan waktu yang lama & berpotensi membuat aplikasi kita jadi seakan “hang”.

Fungsi async getPosts(), harus mengembalikan sebuah obyek Future karena fungsi getPosts() akan mengembalikan hasil di waktu yang belum diketahui kapan di masa depan. Hasil fungsi getPosts() adalah sebuah List yang setiap item nya adalah sebuah obyek InstagramPost, atau disingkat List<InstagramPost> .

Nah, sekarang bagaimana kita bisa memanggil fungsi getPosts() ?

Kita akan memanggil fungsi getPosts() di class InstagramCards di file main.dart. Tapi karena fungsi getPosts() berpotensi mengubah tampilan aplikasi, maka kita perlu mengubah class IntagramCards jadi sebuah StatefulWidget. Kalau kita pakai VSCode, ada cara yang cukup mudah untuk mengubah class InstagramCards menjadi StatefulWidget. Klik kanan di class InstagramCards, lalu klik Refactor… seperti gambar berikut ini

gambar 2 - refactoring class InstagramCards

Setelah klik Refactor… , lalu klik “Convert to StatefulWidget”.

gambar 3 - mengubah class InstagramCards menjadi StatefulWidget

Dan class InstagramCards akan berubah jadi StatefulWidget. Akan ada class baru di bawah class InstagramCards, yaitu _InstagramCardsState yang memungkinkan kita mengubah tampilan aplikasi sesuai yang kita mau.

Kembali ke fungsi getPosts, sekarang kita bisa memanggil fungsi getPosts di class _InstagramCardsState. Untuk best practice, kita perlu memanggil getPosts di dalam class _InstagramCardsState, seperti berikut ini:

...

	class InstagramCards extends StatefulWidget {
	  @override
	  _InstagramCardsState createState() => _InstagramCardsState();
	}

	class _InstagramCardsState extends State {
	  Future<List<InstagramPost>> posts;

	  @override
	  void initState() {
		super.initState();
		posts = getPosts();
	  }

	  @override
	  Widget build(BuildContext context) {
		...

Class _InstagramCardsState punya fungsi build() yang dijalankan setiap kali state berubah. Kenapa kita tidak memanggil fungsi getPosts() di fungsi build(), melainkan di fungsi initState() ? Karena fungsi build() akan dipanggil setiap kali tampilan berubah, dan ini akan sangat sering terjadi. Kalau kita panggil fungsi getState() di dalam build(), kita akan menembaki API lebih sering dari yang dibutuhkan, berpotensi membuat aplikasi kita jadi lebih lambat.

Di kodingan di atas, setelah kita panggil fungsi getPosts(), kita mendapatkan obyek posts yang tipenya Future<List<InstagramPost>>. … Ngga perlu takut dengan tipe yang terdengar “asing” dan “rumit” ini ha3… Kalau diterjemahkan, obyek posts cuma bertipe Future yang didalamnya mengandung List berisi InstagramPost.

Sekarang kita bisa pakai obyek posts untuk menampilkan data yang ada didalamnya. Caranya, kita hapus fungsi build() didalam class _InstagramCardsState, lalu copy paste kodingan berikut ini :

...
  @override
  Widget build(BuildContext context) {
    // InstagramPost instagramPost = new InstagramPost(
    //     profilePicture: 'images/insta_profpic.jpg',
    //     username: 'meidika_wardana',
    //     picture: 'https://pintar-android.com/wp_res/insta_pic2.png',
    //     likeCount: 3,
    //     text: 'Lagu romantis dari Jason Mraz :D');

    // return ListView.builder(
    //   itemBuilder: (BuildContext context, int index) {
    //     return InstagramCard(instagramPost);
    //   },
    //   itemCount: 3,
    // );

    return FutureBuilder<List<InstagramPost>>(
      future: posts,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return InstagramCard(snapshot.data[index]);
            },
            itemCount: snapshot.data.length,
          );
        } else if (snapshot.hasError) {
          return Center(
            child: Text(
              "${snapshot.error}",
              textAlign: TextAlign.center,
            ),
          );
        }

        return CircularProgressIndicator();
      },
    );    
  }
  ...

Di kodingan di atas, banyak bagian yang kita komen (//). Bagian itu adalah kodingan asli fungsi build() sebelum kita ubah barusan. Kemudian kita buat supaya fungsi build() mengembalikan sebuah listview dengan menggunakan FutureBuilder. FutureBuilder ini cukup unik. Dia bisa menggunakan obyek posts yang bertipe Future, lalu di bagian builder-nya, kita mendapatkan context dan snapshot. Kita tidak menggunakan context, kita pakai snapshot saja. snapshot ini asalnya dari obyek posts, dan kita bisa mengecek jika snapshot punya data (snapshot.hasData), maka kita menampilkan listview menggunakan data dari snapshot. Kita menampilkan data satu per satu dalam InstagramCard, yang di kodingan di atas ditulis InstagramCard(snapshot.data[index]).

Kita juga bisa mengecek, jika snapshot berisi error (snapshot.hasError), maka kita bisa menampilkan errornya di widget Text.

Di bagian terakhir, kita menampilkan CircularProgressIndicator yang berupa tampilan loading. Tampilan loading ini adalah yang pertama ditampilkan di aplikasi sampai listview ditampilkan (jika snapshot berisi data), atau sampai error ditampilkan (jika snapshot berisi error).

Saatnya kita coba menjalankan aplikasi ini di emulator :D. Kalau tidak ada error, hasilnya akan seperti ini:

gambar 4 - tampilan list dari http request

Tampilan aplikasi di atas, asalnya dari firebase database yang kita ambil menggunakan kodingan2 kita sebelumnya yang cukup panjang di artikel ini. Secara pribadi, penulis sendiri kurang sreg dengan gambar di setiap postingan yang terlalu banyak bagian yang berwarna hitam.

gambar 5 - gambar postingan yang terlalu banyak bagian hitamnya

Kita bisa mengurangi bagian berwarna hitam tersebut, dengan mengeset height (tinggi) container gambar menjadi hanya setinggi gambarnya sendiri. Di file lib/instagram_card.dart, komen 1 baris property height untuk widget Container yang membungkus widget Image.

...
Row(
  //row #2
  children: [
	Expanded(
	  child: Container(
		child: // Image.asset(_instagramPost.picture)
			Image.network(
		  _instagramPost.picture,
		  fit: BoxFit.contain,
		  // height: _screenWidth,
		),
		color: Colors.black,
	  ),
	)
  ],
),
...

Nah.. sekarang kalau kita jalankan lagi, maka bagian warna hitam akan jadi lebih sedikit & menurut penulis, tampilan aplikasi jadi lebih enak dilihat.

gambar 6 - tampilan akhir aplikasi instagram_list

Sampai di sini artikel pintar-android.com kali ini, mengenai http request menggunakan Flutter. Semoga bermanfaat. Kodingan lengkap untuk tutorial ini ada di https://github.com/meidikawardana/instagram_list_http .

Jangan lupa like page pintar-android.com di FB untuk mendapatkan artikel & tutorial lainnya yang pastinya berguna di dunia pemrograman khususnya android.

===============================================================

Tersedia buku-buku untuk belajar pemrograman Android.

Buku pertama, menginstall Android Studio: https://play.google.com/store/books/details?id=EOufCwAAQBAJ .

Buku kedua, membuat recyclerview yang menampilkan gambar2 dari internet menggunakan json: https://play.google.com/store/books/details?id=b-boDAAAQBAJ .

Buku registrasi user, membuat fitur login & register: https://play.google.com/store/books/details?id=FHMqDwAAQBAJ

Buku Onesignal: https://play.google.com/store/books/details?id=4n1oDwAAQBAJ

Leave a Reply

Your email address will not be published. Required fields are marked *