플러터 GetX에서 Dependency Injection 설정 완벽 가이드

2024. 6. 7. 21:00Flutter/Flutter Programming

반응형

플러터(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

 

나비일기장 [수발일기장] - Google Play 앱

수형자 수발가족및 수발인을 위한 일기장으로 수형생활시기에 따른 정보를 얻을 수 있습니다.

play.google.com

 

 

비공개테스트를 위한 20명의 테스터모집 앱 "테스터 쉐어"

 

https://play.google.com/store/apps/details?id=com.maccrey.tester_share_release

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

반응형