Saat mengembangkan aplikasi Flutter, Anda mungkin ingin meminimalkan biaya pengembangan, menjadikan solusi cepat, andal, dan aman. Dalam panduan ini (atau lebih tepatnya ikhtisar teknis dengan komentar), saya akan menjelaskan cara menghubungkan aplikasi Flutter Anda ke backend menggunakan HTTP REST API dan gRPC. Anda akan mempelajari cara memilih backend yang tepat untuk aplikasi Anda, cara menyiapkannya, dan cara menghubungkan aplikasi Anda ke aplikasi tersebut.

Apa yang harus dipilih?

Bukan rahasia lagi bahwa REST API adalah cara komunikasi paling umum antara frontend dan backend dalam aplikasi web modern dan infrastruktur berbasis layanan mikro. Namun, perlu diperhatikan bahwa layanan mikro juga dapat menggunakan metode komunikasi lain.

HTTP REST API menggunakan protokol HTTP untuk mentransfer data antara klien dan server. Mudah digunakan dan dimengerti oleh sebagian besar pengembang. Untuk menggunakannya, Anda perlu menentukan permintaan yang harus dikirim aplikasi Anda ke server, serta struktur respons yang ingin Anda terima. Artikel ini memberikan contoh penggunaan paket Dio.

gRPC (Panggilan Prosedur Jarak Jauh Google) adalah pendekatan baru untuk komunikasi antara klien dan server, berdasarkan arsitektur RPC sumber terbuka. Ia menggunakan format pertukaran pesan Protobuf, yang merupakan format yang sangat efisien untuk bertukar pesan dengan tingkat pengemasan yang tinggi (berkat penggunaan paksa fitur http/2) untuk membuat serial data terstruktur. Dalam beberapa kasus, penggunaan gRPC API mungkin lebih efisien dibandingkan REST API.

Dalam mengembangkan suatu aplikasi, frontend dan backend biasanya dibuat oleh orang yang berbeda dengan kompetensi yang berbeda pula. Alat seperti swagger dan redoc digunakan untuk memberikan instruksi penggunaan untuk REST. Dalam kasus gRPC, frontend menerima kode yang hampir siap diimplementasikan. Perlu juga dipertimbangkan fakta bahwa jika proyek melibatkan aplikasi web, penggunaan gRPC untuk aplikasi seluler mungkin terlalu mahal.

Menghubungkan dengan HTTP REST

Untuk bekerja dengan REST API, saya sarankan menggunakan paket Dio karena lebih fungsional dan nyaman dibandingkan paket http standar. Jika Anda telah membuat aplikasi web, ini mirip dengan aksio.

Untuk menggunakan Dio, Anda perlu membuat kelas untuk bekerja dengan koneksi jaringan, di mana Anda akan menentukan permintaan yang harus dikirim aplikasi Anda ke server, serta struktur respons yang ingin Anda terima.

“ flutter pub tambahkan dio ”

Tambahkan paket dio ke proyek Anda

Mari buat kelas untuk bekerja dengan koneksi jaringan:

import 'package:dio/dio.dart';

class NetworkService {
  late final Dio _dio;
  final JsonEncoder _encoder = const JsonEncoder();
  static final NetworkService _instance = NetworkService.internal();

  NetworkService.internal();

  static NetworkService get instance => _instance;

  Future<void> initClient() async {
    _dio = Dio(
      BaseOptions(
        baseUrl: Constant.baseUrl,
        connectTimeout: 60000,
        receiveTimeout: 6000,
      ),
    );
// A place for interceptors. For example, for authentication and logging
  }

  Future<dynamic> get(
    String url, {
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final response = await _dio.get(url, queryParameters: queryParameters);
      return response.data;
    } on DioError catch (e) {
      final data = Map<String, dynamic>.from(e.response?.data);
      throw Exception(data['message'] ?? "Error while fetching data");
    } catch (e) {
      rethrow;
    }
  }

  Future<dynamic> download(String url, String path) async {
    return _dio.download(url, path).then((Response response) {
      if (response.statusCode! < 200 || response.statusCode! > 400) {
        throw Exception("Error while fetching data");
      }
      return response.data;
    }).onError((error, stackTrace) {
      throw Exception(error);
    });
  }

  Future<dynamic> delete(String url) async {
    return _dio.delete(url).then((Response response) {
      if (response.statusCode! < 200 || response.statusCode! > 400) {
        throw Exception("Error while fetching data");
      }
      return response.data;
    }).onError((DioError error, stackTrace) {
      _log(error.response);
    });
  }

  Future<dynamic> post(String url, {body, encoding}) async {
    try {
      final response = await _dio.post(url, data: _encoder.convert(body));
      return response.data;
    } on DioError catch (e) {
      throw Exception(e.response?.data['detail'] ?? e.toString());
    } catch (e) {
      rethrow;
    }
  }

  Future<dynamic> postFormData(String url, {required FormData data}) async {
    try {
      final response = await _dio.post(url, data: data);
      return response.data;
    } on DioError catch (e) {
      throw Exception(e.response?.data['detail'] ?? e.toString());
    } catch (e) {
      rethrow;
    }
  }

  Future<dynamic> patch(String url, {body, encoding}) async {
    try {
      final response = await _dio.patch(url, data: _encoder.convert(body));
      return response.data;
    } on DioError catch (e) {
      throw Exception(e.response?.data['detail'] ?? e.toString());
    } catch (e) {
      rethrow;
    }
  }

  Future<dynamic> put(String url, {body, encoding}) async {
    try {
      final response = await _dio.put(url, data: _encoder.convert(body));
      return response.data;
    } on DioError catch (e) {
      throw e.toString();
    } catch (e) {
      rethrow;
    }
  }
}

Contoh

final NetworkService _client;

Future<String> login(LoginRequest loginRequest) async {
  try {
    final jsonData = await _client.post(
      "${Constant.baseUrl}/v1/auth/login",
      body: loginRequest.toJson()
    );
    return jsonData['access_token']
  } catch (e) {
    rethrow;
  }
}

Terhubung dengan gRPC

Untuk bekerja dengan gRPC, Anda perlu menggunakan kode yang dihasilkan berdasarkan file proto. Buat layanan untuk pekerjaan, yang akan menggunakan kelas HelloClient yang dihasilkan menggunakan gRPC. Saat Anda membuat instance HelloClient, Anda harus meneruskannya ke saluran yang akan digunakan untuk mengirim permintaan.

Sekarang, integrasikan klien gRPC yang dihasilkan ke dalam aplikasi Flutter Anda:

“ flutter pub tambahkan grpc ”

Tambahkan paket grpc ke proyek Anda

Membuat layanan untuk bekerja:

import 'package:grpc/grpc.dart';
//import your autogenerate code
import '../services/proto/hello.pbgrpc.dart';

class HelloService {

  ///here enter your host without the http part
  String baseUrl = "example.com";

  HelloService._internal();
  static final HelloService _instance = HelloService._internal();

  factory HelloService() => _instance;

  ///static HelloService instance that we will call when we want to make requests
  static HelloService get instance => _instance;
   ///HelloClient is the  class that was generated for us when we ran the generation command
  ///We will pass a channel to it to intialize it
  late HelloClient _helloClient;

  ///this will be used to create a channel once we create this class.
  ///Call HelloService().init() before making any call.
  Future<void> init() async {
    final channel = ClientChannel(
      baseUrl,
      port: 443,
      options: const ChannelOptions(),
    );
    _helloClient = HelloClient(channel);
  }

  ///provide public access to the HelloClient instance
  HelloClient get helloClient {
    return _helloClient;
  }
}

Di fungsi utama Anda, inisialisasi kelas HelloService seperti di bawah ini.

HelloService().init();

Lakukan panggilan gRPC

Future<void> sayHello() async {
  try {
    HelloRequest helloRequest = HelloRequest();
    helloRequest.name = "Itachi";
    var res = await HelloService.instance.helloClient.sayHello(helloRequest);
  } catch (e) {
    print(e);
  }
}

Membandingkan REST dan gRPC untuk Aplikasi Flutter

  • Keuntungan REST: Sederhana, mudah dimengerti, didukung secara luas, dapat di-cache, dan cocok untuk sebagian besar aplikasi.
  • Kekurangan REST: Latensi lebih tinggi, serialisasi kurang efisien, kemampuan streaming terbatas.
  • Keunggulan gRPC: Latensi rendah, serialisasi efisien, dukungan streaming, pustaka klien yang kuat, dan ideal untuk aplikasi real-time dan layanan mikro.
  • Kekurangan gRPC: Kurva pembelajaran yang lebih curam, tidak dapat dibaca oleh manusia, kurang mendukung browser web, dan mungkin berlebihan untuk aplikasi sederhana.

Saat memilih antara REST dan gRPC untuk aplikasi Flutter Anda, pertimbangkan kebutuhan dan persyaratan spesifik aplikasi Anda. REST adalah pilihan yang tepat untuk sebagian besar aplikasi, sedangkan gRPC sangat cocok untuk aplikasi real-time atau aplikasi dengan pola komunikasi antar layanan yang kompleks.

Dalam artikel ini, kita mempelajari cara mengatur aplikasi Flutter dengan backend API, dengan fokus pada dua pendekatan utama: HTTP REST dan gRPC. Kami mendiskusikan desain API, implementasi klien di Flutter.

Dengan memahami kelebihan dan kekurangan masing-masing pendekatan, Anda dapat membuat keputusan yang tepat saat merancang aplikasi Flutter dengan backend API. Pilih pendekatan terbaik untuk aplikasi Anda berdasarkan kebutuhan spesifiknya, dan bangun aplikasi yang efisien, skalabel, dan mudah dikelola.