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

JY Hwang님의 프로필 이미지
JY Hwang

작성한 질문수

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

레스토랑 상세요청 구현하기

이 부분에서 Error: The argument type 'RestaurantDetailModel' can't be assigned to the parameter type 'RestaurantModel'.

작성

·

47

0

import 'dart:convert';
import 'dart:async';
import 'package:colorfactor/common/const/data.dart';
import 'package:colorfactor/common/layout/default_layout.dart';
import 'package:colorfactor/product/component/product_card.dart';
import 'package:colorfactor/restaurant//component/RestaurantCard.dart';
import 'package:colorfactor/restaurant/model/restaurant_detail_model.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class RestaurantDetailScreen extends StatelessWidget {
  final String id;


  const RestaurantDetailScreen({super.key, required this.id});

  Future<Map<String, dynamic>> getRestaurantDetail() async {
    final dio = Dio();

    final accessToken = await storage.read(key: ACCESS_TOKEN_KEY);

    final resp = await dio.get('http://$ip/restaurant/$id',
      options: Options(
        headers: {
          'authorization': 'Bearer $accessToken'
        },
      ),
    );
    return resp.data;
  }

  @override
  Widget build(BuildContext context) {
    return DefaultLayout(
      title: '불타는 덕볶이',
      child: FutureBuilder<Map<String, dynamic>>(
          future: getRestaurantDetail(),
          builder: (_, AsyncSnapshot<Map<String, dynamic>> snapshot) {
            print(snapshot.data);
            if (!snapshot.hasData) {
              return Container();
            }

            final item = RestaurantDetailModel.fromJson(
              json: snapshot.data!,
            );
            return CustomScrollView(
              slivers: [
                renderTop(
                  model: item,
                ),
                renderLabel(),
                renderProducts(),
              ],
            );
          }
      ),
    );
  }

  SliverPadding renderLabel() {
    return SliverPadding(
      padding: EdgeInsets.symmetric(horizontal: 16),
      sliver: SliverToBoxAdapter(
        child: Text(
          '메뉴', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),),
      ),
    );
  }


  renderProducts() {
    return SliverPadding(
      padding: EdgeInsets.symmetric(horizontal: 16),
      sliver: SliverList(
        delegate: SliverChildBuilderDelegate((context, index) {
          return Padding(
            padding: const EdgeInsets.only(top: 16.0),
            child: ProductCard(),
          );
        },
          childCount: 10,
        ),
      ),
    );
  }


  SliverToBoxAdapter renderTop({
    required RestaurantDetailModel model,
  }) {
    return SliverToBoxAdapter(
      child: RestaurantCard.fromModel(
        model: model,
        isDetail: true,
      ),
    );
  }
}

이 강의 진행에서

SliverToBoxAdapter renderTop({ required RestaurantDetailModel model, }) { return SliverToBoxAdapter( child: RestaurantCard.fromModel( model: model, isDetail: true, ), ); } }

이 부분에서 Error: The argument type 'RestaurantDetailModel' can't be assigned to the parameter type 'RestaurantModel'.

이 에러가 뜹니다.

구조를 다시 따라가서 봐도 문제가 없는것 같은데, 아직 이해도가 낮아서 그런지 Detail모델이 왜 Model에 대입되는지가 이해가 안됩니다.

답변 2

0

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

안녕하세요!

혹시 카카오에서 답변 드렸던 분 맞을까요?

아래 코드 위치에 임포트 슬래시 두개 들어가있는 부분이 있습니다.

import 'package:colorfactor/restaurant//component/RestaurantCard.dart';

감사합니다!

0

안녕하세요, 인프런 AI 인턴입니다. JY Hwang님.

현재 발생한 에러는 RestaurantDetailModelRestaurantModel 간의 타입 불일치에서 기인합니다. 에러 메시지 ‘The argument type ‘RestaurantDetailModel’ can’t be assigned to the parameter type ‘RestaurantModel”를 보면, RestaurantCard.fromModel에서 model로 받고 있는 파라미터 타입이 RestaurantModel로 정의되어 있는데, RestaurantDetailModel을 전달하려고 하여 문제가 발생하고 있습니다.

해결 방법으로는 두 가지 선택지가 있습니다:

  1. RestaurantCard.fromModel 함수가 RestaurantModel 타입을 받도록 코드를 수정합니다. model을 넘길 때 필요한 모든 정보를 RestaurantDetailModel에서 RestaurantModel로 변환하여 넘겨줍니다.
  2. RestaurantCard.fromModelRestaurantDetailModel을 직접 지원하도록 코드를 수정합니다.

해결 방법 예시:

Option 1: 모델 객체 변환

이 방식은 RestaurantDetailModel에서 필요한 데이터를 추출하여 RestaurantModel 객체를 생성한 후 이를 호출하는 방식입니다.

import 'package:flutter/material.dart';

@override
SliverToBoxAdapter renderTop({
  required RestaurantDetailModel model,
}) {
  // convert RestaurantDetailModel to RestaurantModel
  final restaurantModel = RestaurantModel(
    // 필요한 값을 RestaurantDetailModel에서 추출
    id: model.id,
    name: model.name,
    // 다른 필요한 필드들 추가
  );

  return SliverToBoxAdapter(
    child: RestaurantCard.fromModel(
      model: restaurantModel,
      isDetail: true,
    ),
  );
}

Option 2: RestaurantCard.fromModel 수정

RestaurantCard.fromModel 함수가 RestaurantDetailModel을 직접 받도록 코드를 수정하여 타입 불일치를 해결할 수 있습니다.

class RestaurantCard extends StatelessWidget {
  final RestaurantModel model;
  final bool isDetail;

  const RestaurantCard({
    Key? key,
    required this.model,
    required this.isDetail,
  }) : super(key: key);

  factory RestaurantCard.fromModel({
    required RestaurantDetailModel model,  // 타입 변경
    required bool isDetail,
  }) {
    return RestaurantCard(
      model: model,
      isDetail: isDetail,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      // your implementation to build the card
    );
  }
}

위 두 가지 방법 중 하나를 선택하여 해결하시면 됩니다.

유사한 질문과 답변을 참고해보세요:
- gorouter질문2
- RatingPagination 렌더링 부분에서 api 요청이 가지 않고 있습니다.
- typedef itemBuilder 제네릭 관련 질문이 있습니다.
- 다시 getDetail호출?

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

JY Hwang님의 프로필 이미지
JY Hwang
질문자

음...도무지 이해가 안되네요... 넵

JY Hwang님의 프로필 이미지
JY Hwang

작성한 질문수

질문하기