기초 입문서에서 보통은 아래와 같이 알려준다.
Do it 플러터 예제
위와 같이 한 파일에서 스테이트 관리 하는 것은 쉽지만,
MVC 패턴 같은 디자인 패턴을 활용하여 코드를 정리 하려고 하면,
스테이트 관리 하는 것도 따로 해줘야 한다.
모든 프레임워크에서 스테이트가 나오는 순간 더 어려워 진다.
플러터는 특히 더 어렵게 느껴진다.
왜냐하면 다트가 typed 언어라서 스테이트 관리하는 obj도 알아야 하기 때문이다.
또한,
flutter console 창에 데이터를 띄었다고 해서 앱화면에 동일한 코드를 써서 띄우려고 하면 안되는 경우가 많다. 그래서 flutter는 ui 디자인 할 때는 쉽지만 data 연결 할 때는 난의도가 급격하게 올라간다.
예제 들어가기 앞써,
아래와 같은 json data가 넘어 온다고 가정 하겠다.
보통 php backend api는 아래와 같다.
// https://localhost:8000/api/fruit/{id?}
[
{
"id": 1,
"name": "Banana",
"stock": 10
}
]
가장 많이 쓰는 GetX를 사용하여 json 형태의 api data를 build widget에 그려보자.
// lib/model/fruit.dart
class Fruit{
final int id;
final String name;
final int stock;
LaravelApiModel({
required this.id,
required this.name,
required this.stock,
});
// json to Map obj
factory Fruit.fromJson(Map<String, dynamic> json) =>
Fruit(
id: json['id'],
name: json['name'],
stock: json['stock'],
);
// Map obj to json
Map<String, dynamic> toJson() =>
{
'id': id,
'name': name,
'stock': stock,
};
}
// lib/controller/api_controller.dart
import 'dart:convert';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import '../model/fruit.dart';
class ApiController extends GetxController{
// indicating this controller is using GetX
static ApiController instance = Get.find();
// defining GetX variable using keyword Rx
late Rx<Fruit> _fruit;
// setting getter
Fruit get fruit => _fruit.value;
void fetch(int id) async {
final response = await http
.get(Uri.parse('http://127.0.0.1:8000/api/furit/$id'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var json = await jsonDecode(response.body)[0];
Fruit whichFruit = Fruit.fromJson(json);
fruit.value = whichFruit;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load');
}
}
}
GetX를 활용하기 위해, lib/main.dart에서
MaterialApp() 을
GetMaterialApp()으로 바꾸는 걸 잊지 말자.
// screen/screen.dart
class Screen extends StatelessWidget {
var controller = Get.put(ApiController());
var apiController = ApiController.instance;
@override
Widget build(BuildContext context) {
apiController.fetch(1);
return Column(
children: [
Row(
children: [
//
Text(apiController.Fruit.name),
],
),
],
);
}
}
이외 FutureBuilder를 사용하여 할 수 도 있다.
이건 flutter official doc에 있는 cookbook에 설명이 잘 되어 있으니 참조 바란다. 검색을 "FutureBuilder" 라고 하면 된다.