Pada tutorial series Flutter kali ini, Konsep Koding akan berbagi tutorial Flutter Bahasa Indonesia mengenai cara get api atau consume API menggunakan Dio, Dio adalah salah satu library atau package di Flutter untuk consume API, Dio memiliki banyak kelebihan.
Tentang Dio Flutter
Klien Http yang kuat untuk Dart, yang mendukung Interceptors, konfigurasi Global, FormData, Pembatalan Permintaan, Pengunduhan file, Timeout, dll.
API untuk Project
Memulai Project dan Koding
1. Pertama tambahkan package Dio dan GetX di pubspec.yaml
dependencies:
flutter:
sdk: flutter
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons:
^1.0.2
# Add this 3 libs
dio: ^4.0.6
get: ^4.6.5
shimmer:
2. Tambahkan dan ubah file di bawah ini lib folder :
lib/account/account.controller.dart
import 'package:dio/dio.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:get/get.dart' hide Response; | |
import 'package:resep/models/account.model.dart'; | |
import 'package:resep/services/account.repository.dart'; | |
import 'package:resep/services/dio.helper.dart'; | |
class AccountController extends GetxController { | |
var isLoading = true.obs; | |
var isError = false.obs; | |
var errmsg = "".obs; | |
var acountData = <UserModel>[].obs; | |
Dio dio = Dio(); | |
@override | |
void onInit() { | |
// TODO: implement onInit | |
getUser(); | |
super.onInit(); | |
} | |
@override | |
void onReady() { | |
super.onReady(); | |
} | |
@override | |
void onClose() { | |
super.onClose(); | |
} | |
Future<List<UserModel>> getUser() async { | |
isLoading(true); | |
try { | |
final result = await ApiClient().getData(ApiConst.path); | |
final List data = result["data"]; | |
isLoading(false); | |
isError(false); | |
acountData.value = data.map((e) => UserModel.fromMap(e)).toList(); | |
return acountData; | |
} catch (e) { | |
isLoading(false); | |
isError(true); | |
errmsg(e.toString()); | |
throw Exception(e); | |
} | |
} | |
showToast(fName, lName, context) { | |
ScaffoldMessenger.of(context).showSnackBar(SnackBar( | |
content: Text("${fName} ${lName}"), | |
)); | |
} | |
} |
lib/account/account.dart
import 'package:flutter/material.dart'; | |
import 'package:get/get.dart'; | |
import 'package:resep/account/account.controller.dart'; | |
import 'package:shimmer/shimmer.dart'; | |
class AccountScreen extends StatelessWidget { | |
const AccountScreen({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
final AccountController productController = Get.put(AccountController()); | |
return Scaffold( | |
appBar: AppBar(title: const Text("Konsep Koding GetX and Dio")), | |
body: Container( | |
alignment: Alignment.topCenter, | |
padding: EdgeInsets.all(20), | |
child: Obx(() { | |
if (productController.isLoading.value) | |
return Shimmer.fromColors( | |
baseColor: Colors.grey[400]!, | |
highlightColor: Colors.grey[300]!, | |
child: ListView.builder( | |
shrinkWrap: true, | |
itemCount: 5, | |
itemBuilder: (context, index) => Container( | |
margin: const EdgeInsets.symmetric( | |
vertical: 10, horizontal: 10), | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.circular(10), | |
color: Colors.white, | |
), | |
height: 100, | |
width: 200, | |
), | |
)); | |
else if (productController.isError.value) | |
return Text( | |
"Error: ${productController.errmsg.value.capitalize}"); | |
else //if loading == true, show progress indicator | |
// ignore: curly_braces_in_flow_control_structures | |
return Container( | |
//if there is any error, show error message | |
child: Column( | |
//if everything fine, show the JSON as widget | |
children: | |
productController.acountData.value.map<Widget>((user) { | |
return Card( | |
child: ListTile( | |
onTap: () { | |
productController.showToast( | |
user.firstName, user.lastName, context); | |
}, | |
leading: CircleAvatar( | |
backgroundImage: NetworkImage(user.avatar), | |
), | |
title: Text(user.firstName), | |
subtitle: Text(user.email), | |
), | |
); | |
}).toList(), | |
)); | |
}))); | |
} | |
} |
lib/models/account.model.dart
import 'dart:convert'; | |
List<UserModel> userModelFromMap(String str) => | |
List<UserModel>.from(json.decode(str).map((x) => UserModel.fromMap(x))); | |
String userModelToMap(List<UserModel> data) => | |
json.encode(List<dynamic>.from(data.map((x) => x.toMap()))); | |
class UserModel { | |
UserModel({ | |
required this.id, | |
required this.email, | |
required this.firstName, | |
required this.lastName, | |
required this.avatar, | |
}); | |
int id; | |
String email; | |
String firstName; | |
String lastName; | |
String avatar; | |
factory UserModel.fromMap(Map<String, dynamic> json) => UserModel( | |
id: json["id"] == null ? null : json["id"], | |
email: json["email"] == null ? null : json["email"], | |
firstName: json["first_name"] == null ? null : json["first_name"], | |
lastName: json["last_name"] == null ? null : json["last_name"], | |
avatar: json["avatar"] == null ? null : json["avatar"], | |
); | |
Map<String, dynamic> toMap() => { | |
"id": id == null ? null : id, | |
"email": email == null ? null : email, | |
"first_name": firstName == null ? null : firstName, | |
"last_name": lastName == null ? null : lastName, | |
"avatar": avatar == null ? null : avatar, | |
}; | |
} |
lib/services/account.repository.dart
import 'package:dio/dio.dart'; | |
import 'package:resep/services/dio.helper.dart'; | |
class ApiClient { | |
Future getData(String path) async { | |
try { | |
final resonse = | |
await Dio(BaseOptions(baseUrl: ApiConst.baseUrl)).get(path); | |
return resonse.data; | |
} on DioError catch (e) { | |
throw Exception(e.message); | |
} | |
} | |
} |
lib/services/dio.helper.dart
class ApiConst { | |
ApiConst._(); | |
static const String baseUrl = "https://reqres.in/api/"; | |
static const String path = "users?page"; | |
} |
Dan ubah
lib/main.dart
import 'package:flutter/material.dart'; | |
import 'package:resep/account/account.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
// This widget is the root of your application. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
theme: ThemeData( | |
// This is the theme of your application. | |
// | |
// Try running your application with "flutter run". You'll see the | |
// application has a blue toolbar. Then, without quitting the app, try | |
// changing the primarySwatch below to Colors.green and then invoke | |
// "hot reload" (press "r" in the console where you ran "flutter run", | |
// or simply save your changes to "hot reload" in a Flutter IDE). | |
// Notice that the counter didn't reset back to zero; the application | |
// is not restarted. | |
primarySwatch: Colors.green, | |
), | |
home: const AccountScreen(), | |
); | |
} | |
} |
Kemudian run project flutter run maka hasilnya akan seperti di bawah ini:
Penjelasan :
lib/account/account.controller.dart adalah logic yang untuk semua aplikasi kita entah itu untuk hit api, menampilkan alert dan logic lainnya
lib/account/account.dart adalah main UI untuk menampilkan hasil dari API yang di binding dengan GetX dari controller
lib/models/account.model.dart adalah untuk mendeklarasi json response dari server
lib/services/account.repository.dart adalah logic untuk repository dari server yang kemudian dikirim ke controller untuk diolah dan dikirimkan ke UI
lib/services/dio.helper.dart adalah layaknya constant untuk api url dsb disini saya buat khusus untuk helper api kita pisah dengan constant lain jadi khusus untuk URL dan API saja.
Source Project
Sekian Tutorial Flutter Get API dengan Dio, GetX dan Shimmer Yang Baik semoga tutorial dari Konsep Koding ini dapat bermanfaat dan membantu kamu yang sedang mempelajari Futter.
#29 Tutorial Membuat UI Login Animasi Keren Flutter
0 Comments