묻고 답해요
137만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
LateInitializationError 발생
selectedColorId가 null일 때 빈 컨테이너를 반환하는 코드를 작성했음에도 불구하고 다음과 같은 에러가 발생합니다(동작은 정상적으로 되긴 합니다).LateInitializationError: Field 'selectedColorId' has not been initialized.
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
Drift 파일 안의 스키마 버전 업데이트?
int get schemaVersion => 1; // DataModel을 변경하면 버전을 올리고 배포 / 현재 원하는 상태인지 확인용데이터 모델을 저희가 새로 만들고 JOIN 시켜서 연동시키는데 실제 출시, 업데이트 환경에서는 방금과 같이 모델구조에 변화가 오는 상황에서 버전 관리 해주고 문서화 하는게 맞는 건가요?해당 스키마 버전이 실제 구동환경에는 영향이 없고 수업이라서 넘어간 상황인지 궁금합니다.
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
생성날짜를 테이블에 추가하는 이유?
안녕하세요 테이블 ID는 주 식별자로 불러와야하는거 이해했고색상 칼럼은 JOIN하기 위해 새로운 테이블의 값이라는거 이해했습니다그런데 생성 날짜는 왜 추가한건지 설명해주실수 있나요?이미 테이블 연동은 1:1로 ID 로 가능하고 가져오려고 하는 데이터는 색상값이기만 한걸로 이해했습니다.
-
해결됨Flutter로 SNS 앱 만들기
데스크탑에서 작업한 프로젝트 파일을 다른 컴퓨터에서 열어볼때 에러나가 나는 이유를 알고 싶어요
데스크탑에서 강의중인 작업한 프로젝트 파일을 노트북에서 열어볼때 에러나가 나는 이유를 알고 싶어요 주위에 도움 받을때가 없어서요.데트크탑 dart 3.5.1,flutter 3.24.1노트북 dart 3.4.3 flutter 3.22.2 노트북 setting에서Languages&Frameworks/ dart,flutter 설정을 제대로 되었습니다 근데 이렇게 에러는 어떻게 확인해야 합니까 노트북 dart와 flutter 이 같아야 하나요.강의질문가 달라서 지송합니다.강의 받다가 프로젝트를 다른곳에서 작업하게 되어서 ... ㅠㅠ
-
미해결플러터와 장고로 1시간만에 퀴즈 앱/서버 만들기 [무작정 풀스택]
24년 8월 기준,, SnackBar 부분 변경
ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: <Widget>[ const CircularProgressIndicator(), Padding(padding: EdgeInsets.only(left: width * 0.036), ), const Text("로딩중,,,") ], ), duration: const Duration( milliseconds: 300 ), ), );으로 변경됨
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
restaurant_provider 부분에서 에러가 발생합니다.
final resp = await repository.paginate( paginationParams: paginationParams, );해당 부분에서The argument type 'PaginationParams' can't be assigned to the parameter type 'PaginationParams? 가 발생하는데요 타입이 불일치 하다는 것 같은데제가 repository의 paginate 코드랑 pagination_params 코드도 다시 확인해 보고 강사님 깃에 올라온 코드랑 비교도 해봤는데 왜 에러가 발생하는지 모르겠네요paginationParams: paginationParams!,paginationParams: paginationParams ?? const PaginationParams(),이런식으로 바꿔봐도 똑같습니다.아래는 제 repository 및 pagination_params 코드입니다.import 'package:basic_ui/common/dio/dio.dart'; import 'package:basic_ui/common/model/pagination_params.dart'; import 'package:basic_ui/common/model/cursor_pagination_model.dart'; import 'package:basic_ui/restaurant/model/restaurant_detail_model.dart'; import 'package:basic_ui/restaurant/model/restaurant_model.dart'; import 'package:dio/dio.dart' hide Headers; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:retrofit/http.dart'; import '../../common/const/data.dart'; part 'restaurant_repository.g.dart'; final restaurantRepositoryProvider = Provider<RestaurantRepository>( (ref) { final dio = ref.watch(dioProvider); final repository = RestaurantRepository(dio, baseUrl: 'http://$ip/restaurant'); return repository; }, ); @RestApi() abstract class RestaurantRepository { factory RestaurantRepository(Dio dio, {String baseUrl}) = _RestaurantRepository; @GET('/') @Headers({ 'accessToken': 'true', }) Future<CursorPagination<RestaurantModel>> paginate({ @Queries() PaginationParams? paginationParams = const PaginationParams(), }); @GET('/{id}') @Headers({ 'accessToken': 'true', }) Future<RestaurantDetailModel> getRestaurantDetail({ @Path() required String id, }); }import 'package:json_annotation/json_annotation.dart'; part 'pagination_params.g.dart'; @JsonSerializable() class PaginationParams { final String? after; final int? count; const PaginationParams({ this.after, this.count, }); PaginationParams copyWith({ String? after, int? count, }) { return PaginationParams( after: after ?? this.after, count: count ?? this.count, ); } factory PaginationParams.fromJson(Map<String, dynamic> json) => _$PaginationParamsFromJson(json); Map<String, dynamic> toJson() => _$PaginationParamsToJson(this); }
-
해결됨Flutter 앱 개발 실전
Riverpod을 하려고 하는데 질문이 있습니다!
현재 강의에서 주로 사용하신 provider와 mvvm패턴을 활용해서 팀프로젝트와 개인프로젝트를 끝낸 상태입니다.근데 자꾸만 할수록 riverpod에 대한 필요성을 느끼게 되어서 상태관리를 바꿔보려고 생각중인데현재 강사님이 강의하신 내용으로도 충분할까요? 아니면 추가적인 강의나 학습이 필요할까요?제 계획은 1. 강사님이 짧게 다루신 riverpod에 대한 내용을 복습하고 깃허브에 작성하신 riverpod으로 적용된 쇼핑몰 프로젝트를 보면서 클론코딩을 해볼 생각입니다.이후에는 그걸 제 개인프로젝트에 적용할 생각이구요.그걸로 충분할까요?아니면 추가적인 학습 후에 1번과 2번을 하는 게 좋을까요?
-
미해결플러터와 장고로 1시간만에 퀴즈 앱/서버 만들기 [무작정 풀스택]
24년 8월 기준 flutter_swiper import 관련
flutter_swiper_view:로 변경되었음.
-
미해결플러터와 장고로 1시간만에 퀴즈 앱/서버 만들기 [무작정 풀스택]
24년 8월 기준,, 버튼 변경
24년에 퀴즈 앱 만들기 참여하신 분들께 도움이 되고자 남깁니다. 마지막 퀴즈 풀기 버튼 은 아래와 같이 변경되었습니다.child: ElevatedButton( style: ElevatedButton.styleFrom( foregroundColor: Colors.white, backgroundColor: Colors.deepPurple, ), onPressed: () {}, child: const Text( '지금 퀴즈 풀기', style: TextStyle(color: Colors.white), ), ),
-
해결됨Flutter 앱 개발 기초
Expanded 하니 에러가 나는데 이유를 모르겠습니다.
사진에 빨간 박스 부분 Expanded 하는데 정답 코드와 비슷한데 무슨 이유인지 에러가 나는데 잘 모르겠네요. Expanded 적용 전 코드Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// 11 ★ until next Reward Text( "11 ★ until next Reward", style: TextStyle( color: starbucksAccentColor, fontWeight: FontWeight.bold, fontSize: 16, ), ), /// 진행율 ], ), ...Expanded 적용 후 코드(일부분)Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// 11 ★ until next Reward Text( "11 ★ until next Reward", style: TextStyle( color: starbucksAccentColor, fontWeight: FontWeight.bold, fontSize: 16, ), ), /// 진행율 ], ), ), ...전체코드import 'package:flutter/material.dart'; /// Starbucks 메인 색상 Color starbucksPrimaryColor = Color.fromARGB(255, 83, 184, 138); /// Starbucs 포인트 색상 Color starbucksAccentColor = Color.fromARGB(255, 199, 176, 121); class StarbucksHome extends StatelessWidget { const StarbucksHome({super.key}); @override Widget build(BuildContext context) { /// 배경 이미지 URL final String backImg = "https://i.ibb.co/2Pz33q7/2021-12-16-12-21-42-cleanup.png"; /// Frequency 이미지 URL final String frequencyImg = "https://i.ibb.co/QcVn97y/2021-12-16-1-33-11.png"; /// 추천 메뉴 final List<Map<String, String>> recommendMenu = const [ { "name": "돌체쿠키라떼", "imgUrl": "https://i.ibb.co/SwGPpzR/9200000003687-20211118142543832.jpg", }, { "name": "아이스 홀리데이 돌체 쿠키 라떼", "imgUrl": "https://i.ibb.co/JHVXZ72/9200000003690-20211118142702357.jpg", }, { "name": "스노우 민트 초콜릿", "imgUrl": "https://i.ibb.co/M91G17c/9200000003693-20211118142933650.jpg", }, { "name": "아이스 스노우 민트 초콜릿", "imgUrl": "https://i.ibb.co/jyZK4C9/9200000003696-20211118143125337.jpg", }, { "name": "스노우 민트 초콜릿 블렌디드", "imgUrl": "https://i.ibb.co/DKkV0rw/9200000003699-20211118143249044.jpg", }, ]; /// 크리스마스 이벤트 이미지 URL final String eventImg = "https://i.ibb.co/Fb0q43T/IMG-F9-BA5-CBCB476-1.jpg"; return Scaffold( body: CustomScrollView( slivers: [ /// Tip: 스크롤시 배경이 사라지게 할려면 SliverAppBar를 사용 SliverAppBar( // automaticallyImplyLeading: false, expandedHeight: 252, // 최대확장되었을때 높이 pinned: true, // 스크롤시 bottom 영역을 화면 상단에 고정할지 여부 snap: false, // 스크롤 중간에 멈출때 자동으로 AppBar를 펼쳐서 배경을 모두 보여줄지 여부 floating: true, // ?? backgroundColor: Colors.white, /// 스크롤시 사라지는 영역 flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: Stack( children: [ /// 배경이미지 Positioned.fill( bottom: 60, child: Image.network( backImg, fit: BoxFit.cover, ), ), /// 배경 위 위젯 Positioned( top: 24, left: 24, bottom: 60, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "한 해의 마무리,\n수고 많았어요💖", style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold), ), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// 11 ★ until next Reward Text( "11 ★ until next Reward", style: TextStyle( color: starbucksAccentColor, fontWeight: FontWeight.bold, fontSize: 16, ), ), /// 진행율 ], ), /// 1/12 ★ RichText( text: TextSpan( children: [ TextSpan( text: '1', style: TextStyle( color: Colors.black, fontSize: 42, fontWeight: FontWeight.bold, ), ), TextSpan( text: ' / ', style: TextStyle( color: Colors.grey, fontSize: 28, fontWeight: FontWeight.bold, ), ), TextSpan( text: '12 ★', style: TextStyle( color: starbucksAccentColor, fontSize: 28, fontWeight: FontWeight.bold, ), ), ], ), ), ], ) ], ), ), ], ), ), /// 스크롤시 남아있는 영역 bottom: PreferredSize( preferredSize: Size.fromHeight(52), // 영역 높이 child: Container( height: 52, color: Colors.white, padding: EdgeInsets.only(left: 24, right: 12), child: Row( children: [ /// What's New GestureDetector( onTap: () {}, child: Row( children: [ Icon( Icons.mail_outline, color: Colors.grey, ), SizedBox(width: 8), Text( "What's New", style: TextStyle(fontSize: 18), ), ], ), ), SizedBox(width: 32), /// Coupon GestureDetector( onTap: () {}, child: Row( children: [ Icon( Icons.confirmation_num_outlined, color: Colors.grey, ), SizedBox(width: 8), Text( "Coupon", style: TextStyle(fontSize: 18), ), ], ), ), Spacer(), /// Alarm IconButton( onPressed: () {}, icon: Badge( backgroundColor: starbucksPrimaryColor, smallSize: 12, child: Icon( Icons.notifications_outlined, size: 32, color: Colors.grey, ), ), ) ], ), ), ), ), ], ), ); } }
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
GestureDetector 부분 onTap 함수 VoidCallBack 함수로 감싸는 이유?
아래의 코드중에 온탭 생성자 부분에서 바로 onTap(e)를 사용하지 않고 보이드콜백 함수로 감싸줘야하는 이유가child: GestureDetector( onTap: () { ontap(e); },해당 부분에서 onTap 메소드? 함수가 받는 형식은제스처콜백 타입으로 typedef GestureTapCallback = void Function(); 이지만 저희가 생성한 새로운 자료형은 void Function(String selectedColorName);형태이기때문에 완전한 형식을 지켜주는 (){} 형태가 최 상단에 위치하고 그 아래에 저희가 사용하고자 하는 형태로 만들어진 함수를 다시 불러와줌으로서 논리적으로 작동하게 만들어주는게 맞나요?생성한 onTap함수만 넣어서 에러를 읽어봤는데 제대로 이해가 안되서 질문 남깁니다.
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
controller 질문드립니다
안녕하세요 코팩님 전자액자 복습 중에 문득 헷갈리는게 생겨서 질문드립니다.class _HomeScreenState extends State<HomeScreen> { Timer? timer; PageController controller = PageController();여기에서 controller 부분이 잘 이해가 안 가는데요,controller를 사용하려면 위와 같이 PageController controller = PageController();와 같은 형식으로 정의를 해야하는 건가요?웹뷰 프로젝트에서도 controller 정의하실때 WebviewController controller = WebviewController()..~~ 식으로 정의하셨는데,위와 같은 형식으로 정의를 하는 것인지와 또 controller 바로 앞 타입의 정체와 우항의 정체는 정확히 무엇인지 궁금합니다. 좌항 controller 앞의 PageController는 무엇의 타입이고 (정체가 무엇인지),우항도 정체가 무엇인지,또 controller를 사용하고자 하면 저런 형식으로 정의해야하는 것인지 궁금합니다!
-
해결됨Flutter 앱 개발 실전
riverpod의 provider 사용
안녕하세요 선생님 !!강의 잘보고 있습니다.Provider : 수신측에 변경 사항을 알리지 않음 라고 하셔서 코드를 작성해보았습니다. countprovider안에서 ref.watch(towProvider) 사용해봤는데요 우선 여기서 watch를 써서 상태가 바뀐건 이해합니다. 그래서 "counter 생성자" 가 계속 출력되고요 . 근데 main함수에서 counterProvider 를 ref.watch했는데 화면이 계속 갱신 되는 건 이해가 가지 않습니다. 수신측에 변경 사항을 알리지 않음 이라고 하셔서 여기서는 호출해도 변함이 없겠구나 라고 생각했습니다... import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; final towProvider= NotifierProvider<Two, int>( (){return Two();} ); final counterProvider = Provider<Counter>((ref) { print("hello"); int num=ref.watch(towProvider); return Counter(num:num);}); class Two extends Notifier<int>{ Two(){ print("Two 생성자"); } @override int build() => 0; int add() => state++; } class Counter { Counter ({required this.num}){ print("Counter 생성자"); } int num; int getIncreasedNumber() => num ++; } void main() { runApp( const ProviderScope( child: MaterialApp( debugShowCheckedModeBanner: false, home: MyApp(), ), ), ); } class MyApp extends ConsumerWidget { const MyApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { print("build"); Counter counter = ref.watch(counterProvider); return Scaffold( body: Center( child: Text( "${counter.num}", style: const TextStyle( fontSize: 24, ), ), ), floatingActionButton: FloatingActionButton( onPressed: (){ref.read(towProvider.notifier).add();}, child: const Icon(Icons.add), ), ); } }
-
해결됨Flutter 앱 개발 실전
재생불가
강의 재생이 안되 수강할수가 없습니다.회사 지원으로하는거라서 기한내에 수강을 할수 없으면 책임지셔야합니다.
-
해결됨Flutter로 메신저앱 만들기
MessageCardWidget에 프로필 사진과 이름이 남는 이유
54강에서 채팅방 안에 카드 위젯에는 이름과 프로필사진이 남아있는 이유를 모르겠습니다. 앱을 껐다가 켜도 왜 초기화가 되지않는지 이유를 알고싶습니다.
-
미해결Flutter 중급 2편 - 실전 앱 개발 - 미국 주식 앱 (with 클린 아키텍처)
클린아키텍처 의존관계 관련
안녕하세요.클린아키텍쳐에 대해 다시 공부하다가 근본적인 궁금증이 생겨서 질문 드립니다.저는 강사님 강의를 수강하였고 구글에 여러 레포지토리를 참고하며 아래 구조로 프로젝트를 진행하였습니다. 그러나 최근 java + spring architecture 를 공부하다가 모바일쪽의 클린아키텍쳐와 일부 개념이 충돌하여 혼란을 겪고 있습니다. 위의 그림과 같이 바깥의 presentation/repository 와 같은 계층이 usecase 를 의존하여 개발해야 비즈니스로직(usecase / entity) 가 presentation/repository 의 변화의 의존적이지 않고 온전한 비즈니스 로직을 구현할 수 있습니다. 이러한 문제를 해결하기 위해 백엔드 진영에서는 헥사고날 아키텍쳐로 구현하는 듯 합니다. 참고) https://www.youtube.com/watch?v=saxHxoUeeSw04:00 ~ 06:30, 08:20 ~ 14:00 모바일 진영에서는 domain layer 의 usecase 가 repository 를 그대로 참조하고 있어(물론 개념적으로는 인터페이스를 참조) repository 의 변경에 따른 usecase 변화로 비즈니스로직 및 도메인이 손상될 수 있다고 생각하는데 대부분 그냥 사용하고 있습니다. 그래서 제가 잘 못 이해한 것인지 아니면 다른 이유가 있는 것인지 강사님의 의견이 궁금합니다.또한 Flutter 테스트 기초 다음 강의는 언제 나오는지도 궁금합니다 ㅎㅎ 감사합니다.
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
지도 위치정보 항상 확인하는 권한 어떻게 확인하셨나요?
해당 강의에서 앱 실행중에 IOS용 geolocator 셋업 하는 과정 중에 백그라운드 권한 주는 내용이 문서에 없는데 추가 하셨잖아요 이런건 어떻게 알게되고 추가 하신 건지 궁금해서 질문 남깁니다.
-
미해결[2024 최신] [코드팩토리] [초급] Flutter 3.0 앱 개발 - 10개의 프로젝트로 오늘 초보 탈출!
위젯과 클래스 차이가 뭔가요?
안녕하세요 선생님지금까지 MaterialApp, Scaffold, Center, Text가 '위젯'이라고 배웠는데요0:28에서 Text를 '클래스'라고 말씀하시는데'위젯'과 '클래스'는 같은거라고 생각하면 되는건가요?
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
Login_Screen에서의 상태관리에 대한 질문입니다
안녕하세요~ 강의를 다 듣고 나니 질문이 있습니다login screen의 상태관리에 대한 질문인데요! id, pw를 강의에서는 그냥String username = ''; String password = '';로 View내부에 선언하고 TextField의 onChanged를 통해서 저 값들을 변경하고 ref .read(userMeProvider.notifier) .login(username: username, password: password);이런식으로 넘겨주었는데,username, password 값도 상태관리를 하려면 또 이거에 관련된 프로바이더를 만들어야 하는건가요?? 추가로 id, pw값에 따라 button을 enabled - disabled 시키려면 또 이거와 관련된 프로바이더를 추가로 만들어야 하는건가요?? 이런식으로 하면 한 화면에서도 프로바이더가 굉장히 많이 만들어지게 되는데 이런 방식이 맞는지 궁금합니다..또 그 화면에서만 쓰는데도 전역으로 프로바이더들이 굉장히 많이 선언될거같아요.. 강의에서는 되게 굵직굵직한 data들을 전역 provider로 만들어서 굉장히 편했는데,앱을 개발하다보면 그 화면에서만 필요한 데이터들도 많을거고 단순히 버튼 상태처럼 bool값도 엄청 많을텐데 추후 테스트를 위해서 로직을 분리하려면이런것도 싹 다 프로바이더로 만들어야 하는것인가요..?
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
리프레시 토큰이 만료될 때 AlertDialog를 그리고 싶습니다.
리프레시 토큰이 만료될 때 바로 login screen으로 이동하는 것이 아니라 다이얼로그를 띄운 후 확인 버튼을 누르면 화면 이동을 하고 싶은데 이 showDialog를 어디서 해야 할지 난관에 빠졌습니다. 현재는 리프레시가 만료되면dio interceptor에서 authProvider의 logout() 을 통해userMeProvider의 logout()을 호출해 state를 null로 만들고,goRouter가 state가 null이면 바로 로그인 스크린으로 redirect 시키고 있는데이 흐름이 뷰에서 이루어지는 것이 아니라서 context가 필요한 showDialog를 어느 부분에서 구현해야 할지 감이 안 잡힙니다.state를 null로 만들기 전에 다이얼로그를 띄우려면AuthProvider에서 userMeProvider의 logout를 호출하기 전에 실행되어야 할 것 같기도 한데 logout() { // showDialog()??? ref.read(userMeProvider.notifier).logout(); }결국 view단에서 호출하는 것이 아니기 때문에 context를 얻어올 방법이 떠오르지 않네요...