Flutter
이론
Async Technique

Async Technique

Reference

본 게시물은 코드팩토리 - Flutter 중급 강의 (opens in a new tab)을 참고해서 만들어졌습니다.

State Notifier With

기존에 데이터를 받아오는 화면은 이런식으로 구성이 되어있었다.

restaurant_screen.dart
  // json 데이터에서 data 키 안의 Resstaurant 배열을 가져오는 함수
  Future<List<RestaurantModel>> paginateRestaurant({required WidgetRef ref}) async {
    final dio = ref.watch(dioProvider);
    final CursorPagination<RestaurantModel> resp = await RestaurantRepository(dio, baseUrl: 'http://$ip/restaurant').paginate();
    return resp.data;
  }
  ... 
  중략
  ...
        FutureBuilder(
          future: paginateRestaurant(ref: ref),
          builder: (context, snapshot) {
            if (!snapshot.hasData) {
              return const Center(child: CircularProgressIndicator());
            }
 
            return ListView.separated(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                final pItem = snapshot.data![index];
 
                return GestureDetector(
                    onTap: () {
                      Navigator.of(context).push(MaterialPageRoute(
                        builder: (_) => RestaurantDetailScreen(
                          id: pItem.id,
                        ),
                      ));
                    },
                    child: RestaurantCard.fromModel(model: pItem));
              },
              separatorBuilder: (context, index) {
                return const SizedBox(height: 16.0);
              },
            );
          },
        )

위와 같은 방식으로 스크린을 구성하게 되면 데이터를 받고 처리하는 로직을 View에서 구현해줘야하기 때문에 코드가 깔끔하지 못하다.

이를 해결하기위해서 Repository를 StateNotifier를 이용해서 한 번 더 감싸주고 State를 view에서 watch하는 방식으로 변경하면 이 코드가 더 간결해진다.

객체가 생성되자마자 paginate를 실행해주고 state를 통해서 view를 업데이트 해줄 StateNotifier를 만들어준다.

final restaurantProvider = StateNotifierProvider<RestaurantStateNotifier, List<RestaurantModel>>((ref) {
  final Dio dio = ref.read(dioProvider);
  final RestaurantRepository repository = RestaurantRepository(dio);
  return RestaurantStateNotifier(repo: repository);
});
 
class RestaurantStateNotifier extends StateNotifier<List<RestaurantModel>> {
  late final RestaurantRepository _repository;
  RestaurantStateNotifier({required RestaurantRepository repo})
      : super([]) {
    _repository = repo;
    paginate();
  }
 
  void paginate() async {
    CursorPagination<RestaurantModel> resp = await _repository.paginate();
    state = resp.data;
    
  }
}