인프런 커뮤니티 질문&답변

star님의 프로필 이미지
star

작성한 질문수

[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!

RatingsPagination 렌더링하기

RatingPagination 렌더링 부분에서 api 요청이 가지 않고 있습니다.

작성

·

270

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

코드팩토리 디스코드
https://bit.ly/3HzRzUM

Flutter 강의를 구매하시면 코드팩토리 디스코드 서버 플러터 프리미엄 채널에 들어오실 수 있습니다! 디스코드 서버에 들어오시고 저에게 메세지로 강의를 구매하신 이메일을 보내주시면 프리미엄 채널에 등록해드려요! 프리미엄 채널에 들어오시면 모든 질의응답 최우선으로 답변해드립니다! RatingPagination 렌더링 강의에서 http://ip/restaurant/:rid/rating으로 요청이 가지 않고 있습니다! 어떤 부분을 놓치고 있을까요? 
  • restaurant_detail_screen.dart
class RestaurantDetailScreen extends ConsumerStatefulWidget { final String id; const RestaurantDetailScreen({required this.id, super.key}); @override ConsumerState<RestaurantDetailScreen> createState() => _RestaurantDetailScreenState(); } class _RestaurantDetailScreenState extends ConsumerState<RestaurantDetailScreen> { @override void initState() { super.initState(); ref.read(restaurantProvider.notifier).getDetail(id: widget.id); } @override Widget build(BuildContext context) { final state = ref.watch(restaurantDetailProvider(widget.id)); final ratingsState = ref.watch(restaurantRatingProvider(widget.id)); if (state == null) { return DefaultLayout( child: Center( child: CircularProgressIndicator(), ), ); } return DefaultLayout( title: '불타는 떡볶이', child: CustomScrollView( slivers: [ renderTop( model: state!, ), if (state is! RestaurantDetailModel) renderLoading(), if (state is RestaurantDetailModel) renderLabel(), if (state is RestaurantDetailModel) renderProduct( products: state.products, ), if(ratingsState is CursorPagination<RatingModel>) renderRatings(models: ratingsState.data), ], ), ); } SliverPadding renderRatings({ required List<RatingModel> models, }){ return SliverPadding( padding: EdgeInsets.symmetric(horizontal: 16.0), sliver: SliverList( delegate: SliverChildBuilderDelegate( (_, index) => RatingCard.fromModel( model: models[index], ), childCount: models.length, ), ) ); } //skeleton 사용 -> 로딩중에는 미리보는것 같은 효과 가져오기 SliverPadding renderLoading() { return SliverPadding( padding: EdgeInsets.symmetric( vertical: 16.0, horizontal: 16.0, ), sliver: SliverList( delegate: SliverChildListDelegate( List.generate( 3, (index) => Padding( padding: const EdgeInsets.only(bottom: 32.0), child: SkeletonParagraph( style: SkeletonParagraphStyle( lines: 5, padding: EdgeInsets.zero, ), ), ), ), ), ), ); } // 일반 위젯을 slivers에 추가하려면 SliverToBoxAdapter로 감싸줘야 한다. SliverToBoxAdapter renderTop({ required RestaurantModel model, }) { return SliverToBoxAdapter( child: RestaurantCard.fromModel( model: model, isDetail: true, ), ); } SliverPadding renderLabel() { return SliverPadding( padding: EdgeInsets.symmetric(horizontal: 16.0), sliver: SliverToBoxAdapter( child: Text( '메뉴', style: TextStyle( fontSize: 18.0, fontWeight: FontWeight.w500, ), ), ), ); } SliverPadding renderProduct({ required List<RestaurantProductModel> products, }) { return SliverPadding( padding: EdgeInsets.symmetric(horizontal: 16.0), sliver: SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final model = products[index]; return Padding( padding: const EdgeInsets.only(top: 16.0), child: ProductCard.fromModel( model: model, ), ); }, childCount: products.length, ), ), ); } }  
  • restaurantRatingProviderfinal restaurantRatingProvider = StateNotifierProvider.family<RestaurantRatingStateNotifier, CursorPaginationBase, String>((ref, id){ final repository = ref.watch(restaurantRatingRepositoryProvider(id)); return RestaurantRatingStateNotifier(repository: repository); }); class RestaurantRatingStateNotifier extends StateNotifier<CursorPaginationBase> { final RestaurantRatingRepository repository; RestaurantRatingStateNotifier({ required this.repository, }) : super( CursorPaginationLoading(), ); }
 
  • restaurantRatingRepositoryProvider
final restaurantRatingRepositoryProvider = Provider.family<RestaurantRatingRepository, String>((ref, id) { final dio = ref.watch(dioProvider); return RestaurantRatingRepository(dio, baseUrl: 'http://$ip/restaurant/$id/rating'); }); // http://ip/restaurant/:rid/rating @RestApi() abstract class RestaurantRatingRepository implements IBasePaginationRepository<RatingModel>{ factory RestaurantRatingRepository(Dio dio, {String baseUrl}) = _RestaurantRatingRepository; @GET('/') @Headers({ 'accessToken': 'true', }) Future<CursorPagination<RatingModel>> paginate({ @Queries() PaginationParams? paginationParams = const PaginationParams(), //@Queries() -> PaginationParams 클래스의 값들이 자동으로 쿼리로 변환되어서 요청할 때 들어감! }); }

답변 2

0

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

안녕하세요!

코드를 읽을 수 없는 상태로 붙여넣기 해주시면 봐드리기 어렵습니다.

포매팅이 돼있는 상태로 문제되는 부분만 (에러 위치) 표시해서 전달 부탁드립니다.

감사합니다!

0

안녕하세요, 인프런 AI 인턴입니다. star님의 질문에 답변드리겠습니다.

API 요청이 가지 않는 문제는 여러 가지 원인이 있을 수 있으며, 코드에서 확인할 수 있는 여러 부분들을 점검해야 합니다. 다음의 점검 사항들을 확인해보시면 좋을 것 같습니다:

  1. 네트워크 연결: Flutter 애플리케이션이 올바르게 인터넷에 연결되어 있는지 확인해보세요.
  2. API 엔드포인트: 요청 URL이 올바른지 $ip 부분이 실제 IP 주소로 대체되었는지 확인해야 합니다.
  3. Repository 및 레스토랑 ID: RestaurantRatingRepositoryProvider가 받는 id 매개변수가 올바른 레스토랑 ID인지 확인해보세요.
  4. HTTP 메소드와 헤더: 요청을 보낼 때 HTTP 메소드(GET, POST 등)와 필요한 헤더들이 올바르게 설정되어 있는지 검토하세요.
  5. PaginationParams: paginate 함수 호출 시 PaginationParams가 올바르게 설정되어 있는지 확인하세요.

또한, RestaurantRatingStateNotifierinitState에서 실제로 repository.paginate가 호출되고 있는지, 에러 핸들링이 제대로 되어있는지도 점검이 필요합니다. 코드에서는 RestaurantRatingStateNotifier의 생성자에서 super(CursorPaginationLoading())으로 상태 초기화만 진행되어 있으므로, 실제 페이지네이션 요청이 이루어지는 부분을 확인해야 할 것 같습니다.

위 사항들을 모두 점검해보셨음에도 문제가 해결되지 않는다면, 추가적인 디버깅이 필요합니다. 예를 들어, Dio 인스턴스의 로깅을 활성화하여 실제 HTTP 요청이 발생하는지와 받은 HTTP 응답이 무엇인지를 확인할 수 있습니다.

이 외에도 문제의 원인을 파악하려면 더 많은 정보가 필요할 수 있습니다. 디스코드를 통해 도움을 요청하거나, 더 자세한 로그를 검토해보시는 것을 추천드립니다.

star님의 프로필 이미지
star

작성한 질문수

질문하기