Development/Flutter

[Flutter] get_it 으로 의존성 주입 관리하기 - ListView 적용

가비닷 2024. 5. 19. 11:08

 

 

get_it을 이용하여 상품들의 정보를 Listview에 표시

 

1. Model Class 작성

  • 상품 정보를 담을 모델 클래스 작성
// product.dart

class Product 
  //간단하게 상품명과 가격만 등록
  final String name;
  final double price;

  Product({required this.name, required this.price});
}

 

2. 서비스 및 레포지토리 작성

  • 상품 데이터를 가져오는 ApiService와 이를 관리하는 ProductRepository를 작성합니다.
// services.dart

import 'package:get_it/get_it.dart';

final getIt = GetIt.instance;

class ApiService {
  Future<List<Product>> fetchProducts() async {
    // 실제로는 네트워크 요청을 통해 데이터를 가져와야 합니다.
    // 여기서는 예제 데이터를 반환합니다.
    await Future.delayed(Duration(seconds: 2)); // 네트워크 지연 시간 시뮬레이션
    return [
      Product(name: 'Product 1', price: 29.99),
      Product(name: 'Product 2', price: 49.99),
      Product(name: 'Product 3', price: 19.99),
    ];
  }
}

class ProductRepository {
  final ApiService apiService;//api 서비스 객체 정의

  ProductRepository(this.apiService); //생성자에서 인자로 받음

  Future<List<Product>> getProducts() {//api의 fetchProducts 에서 상품을 가져옴.
    return apiService.fetchProducts();
  }
}


void setupLocator() {
  //Async로 생성하는 경우에는 아닌경우와 다르게 구현해야 함.
  //동기작업인 경우
  //getIt.registerLazySingleton<ApiService>(() => ApiService());
  //getIt.registerLazySingleton<ProductRepository>(() => ProductRepository(getIt<ApiService>()));
  
  //비동기 작업인 경우 
  getIt.registerLazySingletonAsync<ApiService>(() async {
    var apiService = ApiService();
    await apiService.initialize();
    return apiService;
  });
  getIt.registerLazySingletonAsync<ProductRepository>(() async {
    final apiService = await getIt.getAsync<ApiService>();
    return ProductRepository(apiService);
  });
}

 

3. Flutter UI의 Listview에 해당 내용 적용

  • ListView에 상품 정보를 표시하는 Flutter 애플리케이션을 작성합니다.
// main.dart

import 'package:flutter/material.dart';
import 'services.dart';
import 'product.dart';

void main() {
  runApp(MyApp());
  
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    setupLocator();
    //locator setup을 메인에서 처리하긴 하지만 별도로 처리
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ProductListPage(),
    );
  }
}

class ProductListPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final productRepository = getIt<ProductRepository>();

    return Scaffold(
      appBar: AppBar(
        title: Text('Product List'),
      ),
      //비동기로 처리해야 하므로 FutureBuilder를 이용해서 Listview 생성
      body: FutureBuilder<List<Product>>(
        future: productRepository.getProducts(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
            return Center(child: Text('No products available'));
          }

          final products = snapshot.data!;

          return ListView.builder(
            itemCount: products.length,
            itemBuilder: (context, index) {
              final product = products[index];
              return ListTile(
                title: Text(product.name),
                subtitle: Text('\$${product.price}'),
              );
            },
          );
        },
      ),
    );
  }
}