작성
·
270
0
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,
),
),
);
}
}
final 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(),
);
}
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 요청이 가지 않는 문제는 여러 가지 원인이 있을 수 있으며, 코드에서 확인할 수 있는 여러 부분들을 점검해야 합니다. 다음의 점검 사항들을 확인해보시면 좋을 것 같습니다:
$ip
부분이 실제 IP 주소로 대체되었는지 확인해야 합니다.RestaurantRatingRepositoryProvider
가 받는 id
매개변수가 올바른 레스토랑 ID인지 확인해보세요.paginate
함수 호출 시 PaginationParams
가 올바르게 설정되어 있는지 확인하세요.또한, RestaurantRatingStateNotifier
의 initState
에서 실제로 repository.paginate
가 호출되고 있는지, 에러 핸들링이 제대로 되어있는지도 점검이 필요합니다. 코드에서는 RestaurantRatingStateNotifier
의 생성자에서 super(CursorPaginationLoading())
으로 상태 초기화만 진행되어 있으므로, 실제 페이지네이션 요청이 이루어지는 부분을 확인해야 할 것 같습니다.
위 사항들을 모두 점검해보셨음에도 문제가 해결되지 않는다면, 추가적인 디버깅이 필요합니다. 예를 들어, Dio
인스턴스의 로깅을 활성화하여 실제 HTTP 요청이 발생하는지와 받은 HTTP 응답이 무엇인지를 확인할 수 있습니다.
이 외에도 문제의 원인을 파악하려면 더 많은 정보가 필요할 수 있습니다. 디스코드를 통해 도움을 요청하거나, 더 자세한 로그를 검토해보시는 것을 추천드립니다.