플러터(Flutter)에서 GetX의 의존성 주입(Dependency Injection, DI)을 사용하여 앱의 컴포넌트 간 의존성을 관리하고, 테스트 가능하고 유지보수하기 쉬운 코드를 작성하는 방법을 알아보겠습니다. 이 가이드는 GetX의 다양한 DI 기법을 다루며, 이를 실제 프로젝트에 적용하는 방법을 설명합니다.
1. 프로젝트 설정
1.1. 새로운 플러터 프로젝트 생성
먼저 새로운 플러터 프로젝트를 생성합니다
flutter create getx_di_app
cd getx_di_app
1.2. pubspec.yaml 파일 업데이트
프로젝트의 pubspec.yaml 파일에 GetX 패키지를 추가합니다
dependencies:
flutter:
sdk: flutter
get: ^4.6.5
그런 다음 패키지를 설치합니다
flutter pub get
2. GetX에서 의존성 주입 설정
GetX에서는 Get.put(), Get.lazyPut(), Get.putAsync(), Get.create() 등의 메서드를 사용하여 의존성을 주입할 수 있습니다.
2.1. Get.put()
Get.put()은 즉시 객체를 생성하고 주입합니다. 이는 가장 기본적인 의존성 주입 방법입니다.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
// MyController를 GetX에 주입합니다.
Get.put(MyController());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'GetX DI Demo',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// MyController 인스턴스를 Get.find()를 사용하여 가져옵니다.
final MyController controller = Get.find<MyController>();
return Scaffold(
appBar: AppBar(
title: Text('GetX DI Demo'),
),
body: Center(
child: Obx(() {
return Text('Count: ${controller.count}');
}),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
);
}
}
class MyController extends GetxController {
var count = 0.obs;
void increment() {
count++;
}
}
2.2. Get.lazyPut()
Get.lazyPut()은 객체를 필요할 때까지 생성하지 않습니다. 이는 메모리를 절약하는 데 유용합니다.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
// MyController를 필요할 때까지 생성하지 않습니다.
Get.lazyPut<MyController>(() => MyController());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'GetX DI Demo',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// MyController 인스턴스를 Get.find()를 사용하여 가져옵니다.
final MyController controller = Get.find<MyController>();
return Scaffold(
appBar: AppBar(
title: Text('GetX DI Demo'),
),
body: Center(
child: Obx(() {
return Text('Count: ${controller.count}');
}),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
);
}
}
class MyController extends GetxController {
var count = 0.obs;
void increment() {
count++;
}
}
2.3. Get.putAsync()
Get.putAsync()는 비동기적으로 객체를 생성하고 주입합니다. 이는 비동기 초기화가 필요한 객체에 유용합니다.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() async {
// MyController를 비동기적으로 생성하고 주입합니다.
await Get.putAsync<MyController>(() async {
await Future.delayed(Duration(seconds: 2));
return MyController();
});
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'GetX DI Demo',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// MyController 인스턴스를 Get.find()를 사용하여 가져옵니다.
final MyController controller = Get.find<MyController>();
return Scaffold(
appBar: AppBar(
title: Text('GetX DI Demo'),
),
body: Center(
child: Obx(() {
return Text('Count: ${controller.count}');
}),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
);
}
}
class MyController extends GetxController {
var count = 0.obs;
void increment() {
count++;
}
}
2.4. Get.create()
Get.create()는 매번 새로운 인스턴스를 생성합니다. 이는 특정 조건에서 새로운 인스턴스가 필요한 경우에 유용합니다.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
// MyController를 매번 새로운 인스턴스를 생성합니다.
Get.create<MyController>(() => MyController());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'GetX DI Demo',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// MyController 인스턴스를 Get.find()를 사용하여 가져옵니다.
final MyController controller = Get.find<MyController>();
return Scaffold(
appBar: AppBar(
title: Text('GetX DI Demo'),
),
body: Center(
child: Obx(() {
return Text('Count: ${controller.count}');
}),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
);
}
}
class MyController extends GetxController {
var count = 0.obs;
void increment() {
count++;
}
}
3. 의존성 주입과 함께 사용하기
3.1. Service와 Controller 분리
Service 클래스와 Controller 클래스를 분리하여 더 구조화된 코드를 작성할 수 있습니다. 예를 들어, API 요청을 처리하는 Service와 데이터를 관리하는 Controller를 분리합니다.
lib/services/api_service.dart 파일
import 'package:http/http.dart' as http;
class ApiService {
final String baseUrl;
ApiService({required this.baseUrl});
Future<http.Response> fetchData() async {
final response = await http.get(Uri.parse(baseUrl));
if (response.statusCode == 200) {
return response;
} else {
throw Exception('Failed to load data');
}
}
}
lib/controllers/data_controller.dart 파일
import 'package:get/get.dart';
import '../services/api_service.dart';
class DataController extends GetxController {
final ApiService apiService;
var data = {}.obs;
var isLoading = false.obs;
DataController({required this.apiService});
void fetchData() async {
isLoading.value = true;
try {
final response = await apiService.fetchData();
data.value = response.body;
} catch (e) {
Get.snackbar('Error', e.toString());
} finally {
isLoading.value = false;
}
}
}
lib/main.dart 파일
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'controllers/data_controller.dart';
import 'services/api_service.dart';
void main() {
// ApiService를 주입합니다.
final apiService = ApiService(baseUrl: 'https://jsonplaceholder.typicode.com/posts/1');
Get.put(DataController(apiService: apiService));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'GetX DI Demo',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final DataController controller = Get.find<DataController>();
return Scaffold(
appBar: AppBar(
title: Text('GetX DI Demo'),
),
body: Center(
child: Obx(() {
if (controller.isLoading.value) {
return CircularProgressIndicator();
} else if (controller.data.isNotEmpty) {
return Text('Data: ${controller.data}');
} else {
return Text('No data');
}
}),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.fetchData,
child: Icon(Icons.add),
),
);
}
}
4. 결론
이 가이드에서는 플러터와 GetX를 사용하여 의존성 주입을 설정하고 사용하는 방법을 다루었습니다.
GetX의 Get.put(), Get.lazyPut(), Get.putAsync(), Get.create() 등을 활용하여 의존성을 주입하고, Service와 Controller를 분리하여 더 구조화된 코드를 작성하는 방법을 설명했습니다.
이를 통해 플러터 앱에서 더 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.
수발가족을 위한 일기장 “나비일기장”
https://play.google.com/store/apps/details?id=com.maccrey.navi_diary_release
비공개테스트를 위한 20명의 테스터모집 앱 "테스터 쉐어"
https://play.google.com/store/apps/details?id=com.maccrey.tester_share_release
'Flutter > Flutter Programming' 카테고리의 다른 글
Flutter GetX에서 로깅 상세 완벽 가이드 (0) | 2024.06.07 |
---|---|
플러터 GetX에서 코드 제네레이션 상세 완벽 가이드 (0) | 2024.06.07 |
플러터 GetX를 사용한 알림 설정 상세 가이드 (0) | 2024.06.07 |
플러터 GetX에서 스토리지 상세 완벽 가이드 (0) | 2024.06.07 |
플러터 GetX에서 알림 완벽 가이드 (초보자용) (0) | 2024.06.07 |