묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 선생님 또 저입니다
GoRouter 의 redirect 에 provider.redirectLogic 을 넣어주셨는데, 이렇게 설정하면 GoRouter 의 routes 안에서 이동이 일어날때마다 redirectLogic 이 실행되도록 구현하신게 맞나요? 제가 제대로 이해한게 맞는지 확인하고싶어서 글 남깁니다
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 선생님 GoRouter 10 버전을 사용해보고 있는데요
기존에 4, 7 버전에서는 GoRouterState 에 location 속성이 있는데 10 버전에는 없더라구요.Uri 타입의 uri 가 새로 생겼던데location 대신 matchedLocation 을 사용해서 auth_provider.dart 를 만들어도 될까요?
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
자동완성
너무 기초적인 질문이라 죄송합니다.강의 초반부에 StatelessWidget을 만드시는데 단축키를 사용하시는지 갑지가 몇글자 안치셨는데 비어있는 코드가 쭉 생기던데요.단축키인가요....???- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.코드팩토리 디스코드https://bit.ly/3HzRzUMFlutter 강의를 구매하시면 코드팩토리 디스코드 서버 플러터 프리미엄 채널에 들어오실 수 있습니다! 디스코드 서버에 들어오시고 저에게 메세지로 강의를 구매하신 이메일을 보내주시면 프리미엄 채널에 등록해드려요! 프리미엄 채널에 들어오시면 모든 질의응답 최우선으로 답변해드립니다!
-
해결됨[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
provider의 state 초기 생성 시기
riverpod을 사용하는 provider의 경우 초기 state를 (ref) => initialState 형식으로 지정해주도록 되어있습니다. 그런데 궁금한 것이 해당 초기 상태 값이 생성되는 시기가 어떤 view에서 처음으로 watch를 하는 때인 것인지 아니면 app이 처음 build되는 시기인지 궁금합니다. 즉, watch를 하지 않고 read를 통해 state를 변경하는 경우 이미 초기 state가 생성되어있는 상태인 것인지 궁금합니다.
-
해결됨[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 선생님 질문이 있습니다
user/repository/auth_repository.dart위 파일을 작업할때는 retrofit 을 사용하지 않는 이유가 따로 있으신건가요?
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
iOS 실제 기기 Login 테스트 에러
안녕하세요.ip를 확인하고 android와 iOS 기기를 통해 테스트 중 에러가 발생했습니다.android 기기에선 문제 없이 동작하는데 iOS 기기에선 SocketException: Connection failed (OS Error: No route to host, errno = 65), address = 192.168.0.122, port = 3000 메시지와 함께 에러가 발생합니다.퍼미션이 잘못된 것인지 이유를 모르겠어서 질문드립니다!
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 강사님
안녕하세요 강사님 플러터 상태관리 관련해서 검색을 해보니까 최근에는 Provider + Bloc 상태관리를 가장 많이 선호한다고 들었는데 혹시 추후에 Bloc 부분을 강의에 추가하실 예정이 있으신지 여쭈어보고 싶습니다.
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 선생님 강의 잘보고 있습니다
강의를 거의 중후반 정도 까지 보고 있는데, 이리저리 찾아보다 보니 MVVM 디자인 패턴이 주로 앱개발 할때 많이 사용되는 패턴이라고 하더라구요.각 레이어들의 정의를 찾아보니 배달앱 개발 수업에서도UI 를 담당하는 Screen (View)상태를 관리하는 Provider (View Model)api 통신을 담당하는 Repository (Model)이렇게 이해해도 무리가 아닐까요? 아니면 약간 더 들어가야 하는 내용들이 있다면 어떤것들이 있는지 궁굼합니다
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
레포짓토리 dio provider를 왜 read가 아닌watch로 읽어오는 걸까요?
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.코드팩토리 디스코드https://bit.ly/3HzRzUMFlutter 강의를 구매하시면 코드팩토리 디스코드 서버 플러터 프리미엄 채널에 들어오실 수 있습니다! 디스코드 서버에 들어오시고 저에게 메세지로 강의를 구매하신 이메일을 보내주시면 프리미엄 채널에 등록해드려요! 프리미엄 채널에 들어오시면 모든 질의응답 최우선으로 답변해드립니다!
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
vscode로 플러터 디버깅을 할 때 오류가 나면
vscode로 플러터 디버깅을 할 때 오류가 나면 오류가 발생한 지점을 표시하면서 디버깅이 일시중지되고 거기서 f5(계속)을 계속 눌러서 문제되는 지점을 다 확인해야만 디버깅이 재개되는데요, 이게 너무 불편합니다..강의에서보면 안드로이드스튜디오는 그냥 오류메시지만 알려주고 디버깅이 일시정지되거나 그러지 않아서 오히려 디버깅이 편해보이는데, 혹시 선생님께서는 vscode에서도 안드로이드스튜디오식으로 디버깅을 할 수 있게 하는 방법을 아시나요..? 나름대로 찾아보려고 하는데 검색어부터 애매해서 쉽지않네요 ㅠㅠ 그냥 안드로이드스튜디오로 갈아타야할까요..
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
초급강의랑 동시 진행이 가능할까요?
안녕하세요 강사님 현재 초급강의를 진행하면서 중급강의를 결제를 해서 보고있는데요 초급강의 내용들 대부분이 UI쪽 위주인거 같아서 혹시 빠르게 공부를 진행하려면 초급 강의를 건너 뛰거나 중급강의와 동시에 진행하는 방법도 괜찮은지 여쭈어보려고 합니다. (회사에서 급하게 프로젝트를 진행해야 되서 그렇습니다.)
-
해결됨[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
Go router v7 적용후 에러
안녕하세요 코드팩토리님 Authentication 마무리하기 강의를 듣는도중 실행해보니 크게 2가지 에러가 발생했습니다ㅠFlutterError.demangleStackTrace 관련 오류와 DioException [bad response]: The request returned an invalid status code of 401: 아래는 에러 전문입니다. await storage.deleteAll을 해볼까 싶다가도 어디에 삽입해야 작동이될지 몰라서 한번 여쭤보겠습니다! Performing hot restart...Syncing files to device iPhone 14 Pro...Restarted application in 467ms.flutter: [REQ] [GET] http://127.0.0.1:3000/user/me/======== Exception caught by widgets library =======================================================The following assertion was thrown building UncontrolledProviderScope:Got a stack frame from package:stack_trace, where a vm or web frame was expected. This can happen if FlutterError.demangleStackTrace was not set in an environment that propagates non-standard stack traces to the framework, such as during tests.'package:flutter/src/foundation/stack_frame.dart':Failed assertion: line 180 pos 7: 'line != '===== asynchronous gap ===========================''The relevant error-causing widget was: UncontrolledProviderScope UncontrolledProviderScope:file:///Users/idohyeong/.pub-cache/hosted/pub.dev/flutter_riverpod-2.3.6/lib/src/framework.dart:250:12When the exception was thrown, this was the stack: #2 StackFrame.fromStackTraceLine (package:flutter/src/foundation/stack_frame.dart:180:7)#3 MappedIterator.moveNext (dart:_internal/iterable.dart:393:20)#4 WhereTypeIterator.moveNext (dart:_internal/iterable.dart:871:20)#5 new GrowableList.ofOther (dart:core-patch/growable_array.dart:202:26)#6 new GrowableList.of (dart:core-patch/growablearray.dart:152:26)#7 new List.of (dart:core-patch/array_patch.dart:47:28)#8 Iterable.toList (dart:core/iterable.dart:497:7)#9 StackFrame.fromStackString (package:flutter/src/foundation/stack_frame.dart:82:10)#10 StackFrame.fromStackTrace (package:flutter/src/foundation/stack_frame.dart:68:12)#11 FlutterErrorDetails.debugFillProperties (package:flutter/src/foundation/assertions.dart:714:57)#12 DiagnosticableNode.builder.<anonymous closure> (package:flutter/src/foundation/diagnostics.dart:2891:17)#13 DiagnosticableNode.builder (package:flutter/src/foundation/diagnostics.dart:2894:8)#14 _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1290:56)#15 DiagnosticableNode.emptyBodyDescription (package:flutter/src/foundation/diagnostics.dart:2905:77)#16 DiagnosticsNode.toJsonMap.<anonymous closure> (package:flutter/src/foundation/diagnostics.dart:1621:13)#17 DiagnosticsNode.toJsonMap (package:flutter/src/foundation/diagnostics.dart:1650:6)#18 WidgetInspectorService._nodeToJson (package:flutter/src/widgets/widget_inspector.dart:1714:18)#19 WidgetInspectorService._reportStructuredError (package:flutter/src/widgets/widget_inspector.dart:967:44)#20 FlutterError.reportError (package:flutter/src/foundation/assertions.dart:1185:14)#21 _reportException (package:flutter/src/widgets/framework.dart:6807:16)#22 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5385:9)#23 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5541:11)#24 Element.rebuild (package:flutter/src/widgets/framework.dart:5092:7)#25 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5358:5)#26 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5532:11)#27 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5352:5)... Normal element mounting (7 frames)#34 UncontrolledProviderScopeElement.mount (package:flutterriverpod/src/framework.dart:309:11)... Normal element mounting (35 frames)#69 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4231:16)#70 Element.updateChild (package:flutter/src/widgets/framework.dart:3742:18)#71 RawViewElement.updateChild (package:flutter/src/widgets/view.dart:289:16)#72 _RawViewElement.mount (package:flutter/src/widgets/view.dart:312:5)... Normal element mounting (7 frames)#79 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4231:16)#80 Element.updateChild (package:flutter/src/widgets/framework.dart:3742:18)#81 RootElement._rebuild (package:flutter/src/widgets/binding.dart:1299:16)#82 RootElement.mount (package:flutter/src/widgets/binding.dart:1268:5)#83 RootWidget.attach.<anonymous closure> (package:flutter/src/widgets/binding.dart:1221:18)#84 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2733:19)#85 RootWidget.attach (package:flutter/src/widgets/binding.dart:1220:13)#86 WidgetsBinding.attachToBuildOwner (package:flutter/src/widgets/binding.dart:1065:27)#87 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:1047:5)#88 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:1033:7)#92 RawReceivePort.handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)(elided 5 frames from class AssertionError, class Timer, and dart:async-patch)====================================================================================================flutter: [ERR] [GET] http://127.0.0.1:3000/user/me/[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: DioException [bad response]: The request returned an invalid status code of 401.#0 DioMixin.fetch.<anonymous closure> (package:dio/src/dio_mixin.dart:533:7)#1 FutureListener.handleError (dart:async/futureimpl.dart:177:22)#2 Future._propagateToListeners.handleError (dart:async/future_impl.dart:855:47)#3 Future._propagateToListeners (dart:async/future_impl.dart:876:13)#4 Future._completeError (dart:async/future_impl.dart:652:5)#5 SyncCompleter.completeError (dart:async/future_impl.dart:63:12)#6 Completer.completeError (dart:async/futureimpl.dart:27:5)#7 Future.any.onError (dart:async/future.dart:618:45)#8 _RootZone.runBinary (dart:async/zone.dart:1666:54)#9 FutureListener.handleError (dart:async/futureimpl.dart:174:22)#10 Future._propagateToListeners.handleError (dart:async/future_impl.dart:855:47)#11 Future._propagateToListeners (dart:async/future_impl.dart:876:13)<…>======== Exception caught by widgets library =======================================================The following assertion was thrown building UncontrolledProviderScope:Got a stack frame from package:stack_trace, where a vm or web frame was expected. This can happen if FlutterError.demangleStackTrace was not set in an environment that propagates non-standard stack traces to the framework, such as during tests.'package:flutter/src/foundation/stack_frame.dart':Failed assertion: line 180 pos 7: 'line != '===== asynchronous gap ===========================''The relevant error-causing widget was: ProviderScope ProviderScope:file:///Users/idohyeong/Desktop/authentication_practice/lib/main.dart:11:5When the exception was thrown, this was the stack: #2 StackFrame.fromStackTraceLine (package:flutter/src/foundation/stack_frame.dart:180:7)#3 MappedIterator.moveNext (dart:_internal/iterable.dart:393:20)#4 WhereTypeIterator.moveNext (dart:_internal/iterable.dart:871:20)#5 new GrowableList.ofOther (dart:core-patch/growable_array.dart:202:26)#6 new GrowableList.of (dart:core-patch/growablearray.dart:152:26)#7 new List.of (dart:core-patch/array_patch.dart:47:28)#8 Iterable.toList (dart:core/iterable.dart:497:7)#9 StackFrame.fromStackString (package:flutter/src/foundation/stack_frame.dart:82:10)#10 StackFrame.fromStackTrace (package:flutter/src/foundation/stack_frame.dart:68:12)#11 FlutterErrorDetails.debugFillProperties (package:flutter/src/foundation/assertions.dart:714:57)#12 DiagnosticableNode.builder.<anonymous closure> (package:flutter/src/foundation/diagnostics.dart:2891:17)#13 DiagnosticableNode.builder (package:flutter/src/foundation/diagnostics.dart:2894:8)#14 _FlutterErrorDetailsNode.builder (package:flutter/src/foundation/assertions.dart:1290:56)#15 DiagnosticableNode.emptyBodyDescription (package:flutter/src/foundation/diagnostics.dart:2905:77)#16 DiagnosticsNode.toJsonMap.<anonymous closure> (package:flutter/src/foundation/diagnostics.dart:1621:13)#17 DiagnosticsNode.toJsonMap (package:flutter/src/foundation/diagnostics.dart:1650:6)#18 WidgetInspectorService._nodeToJson (package:flutter/src/widgets/widget_inspector.dart:1714:18)#19 WidgetInspectorService._reportStructuredError (package:flutter/src/widgets/widget_inspector.dart:967:44)#20 FlutterError.reportError (package:flutter/src/foundation/assertions.dart:1185:14)#21 _reportException (package:flutter/src/widgets/framework.dart:6807:16)#22 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5385:9)#23 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5541:11)#24 Element.rebuild (package:flutter/src/widgets/framework.dart:5092:7)#25 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5358:5)#26 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5532:11)#27 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5352:5)#28 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4231:16)#29 Element.updateChild (package:flutter/src/widgets/framework.dart:3736:20)#30 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5401:16)#31 Element.rebuild (package:flutter/src/widgets/framework.dart:5092:7)#32 ProxyElement.update (package:flutter/src/widgets/framework.dart:5707:5)#33 Element.updateChild (package:flutter/src/widgets/framework.dart:3720:15)#34 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5401:16)#35 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5541:11)#36 Element.rebuild (package:flutter/src/widgets/framework.dart:5092:7)#37 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2793:19)#38 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:966:21)#39 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:457:5)#40 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1301:15)#41 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1231:9)#42 SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:954:7)#46 RawReceivePort.handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)(elided 5 frames from class AssertionError, class Timer, and dart:async-patch)====================================================================================================
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
CursorPaginationRefetching 상황은 구현인 안된건가요??
안녕하세요 이전에 빠른 답변 주셔서 감사합니다. 현재 FetchMore 로딩 UI 작업하기 강의를 듣고 복습 중입니다. 그중에 CursorPaginationRefetching 상황은 데이터를 들고 있는 상황에서 새로고침을 하여 새로 데이터를 수신하는 중이라 이해 하였습니다. 이 코드가 현재 제가 강의를 진행한 상태에서는 불필요한 코드가 아닌가 생각이 들어서 질문 드립니다. CursorPaginationRefetching 조건은 아래와 같다고 강의하셨습니다. else { // 만약에 데이터가 있는 상황이라면 // 기존 데이털르 보존한채로 Fetch (API 요청)를 진행 if (state is CursorPagination && !forceRefetch) { final pState = state as CursorPagination; state = CursorPaginationRefetching( meta: pState.meta, data: pState.data, ); } 그리고 아래 코드 부분은 어떤 조건이든 무조건 실행되어 새로 데이터를 받아오는 코드입니다. final resp = await repository.paginate( paginationParams: paginationParams, );이 다음에 실행되는 코드는 state에 데이터를 넣는 과정으로 CursorPaginationFetchingMore 조건이 아니면 무조건 else가 실행되어 위에서 받아온 새로운 데이터를 state에 대입하는 과정을 거치게 됩니다. if (state is CursorPaginationFetchingMore) { final pState = state as CursorPaginationFetchingMore; // 기존 데이터에 // 새로운 데이터 추가 state = resp.copyWith( data: [ ...pState.data, ...resp.data, ], ); }else{ state = resp; } 다시 저의 의문점을 정리하면 FetchMore 로딩 UI 작업하기까지 진행한 상태에서 코드를 보면 CursorPaginationFetchingMore 조건이 아니라면 무조건 state = resp 가 실행되기 때문에 state = CursorPaginationRefetching(meta: pState.meta,data: pState.data)를 지정하는 과정이 있든 없든 상관이 없는것 같아보인다는 점 입니다. 결국 CursorPaginationRefetching일때 RestaurantScreen에서 작동하는 로직이 없는 거 같은데 맞나요?? 아니면 제가 놓친 부분이 있나요??
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
서버 제작 관련
안녕하세요 코드팩토리님 현재까지 수업을 잘 따라오고 있는 와중에 결국 플러터 + api 서버가 같이 있어야 어플을 돌릴수 있는데 그렇다면 추후 api서버 제작하는 강의도 해주실수 있으신가요? 그리고 지금 현재 test서버도 플러터로 만드신건지 궁금합니다!
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
Restaurant Pagination의 provider 로직관련입니다.
안녕하세요 상태관리 프로젝트에 적용하기 부분이 많이 어렵네요 여러번 강의를 보고 restaurant_provider.dart의 코드를 보며 이해를 하려 했는데 제가 이해를 한것이 맞는지 몰라 이곳에 질문을 남기게 되었습니다. CursorPagination의 상태 관련 5개중 아래 두가지 상태를 제가 이해한게 맞나요??두가지 모두 로딩중인데 아래 상황에서 로딩중CursorPaginationRefetching: 데이터를 받아온 상태에서 다시 새로고침을 하여 로딩 중 CursorPaginationFetchMore: 데이터를 받아온 상태에서 새로운 데이터를 추가 하는 중 바로 반환하는 상황바로 반환하는 상황이라는 것이 데이터를 받아 오는 중, 즉 로딩중 일때나 더이상 추가 데이터가 없을 때paginate() 함수 바로 빠져 나와야 한다는 뜻인가요??그리고 fetchMore가 아닐때 - 새로고침의 의도가 있을 수 있다. fetchMore가 아닐때라고 주석을 달아 주셨는데 이것은 false일때라는 뜻인가요?? 그럼 감사합니다 .
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
텍스트필드 디자인하기 강의 중 변수선언 질문
final baseBorder = const OutlineInputBorder( borderSide: BorderSide( color: INPUT_BORDER_COLOR, ), );이 코드를 CustomTextFormField 클래스의 필드로 넣지 않고 build 메서드 안에 작성하신 이유가 따로 있을까요?이렇게 작성하면 렌더링될때마다 baseBorder가 만들어져야하니 메모리관리면에서 손해인거 아닌가 싶어서요!
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
gorouter 7 버전 상세화면 이동 오류
안녕하세요강의 실습 중 오류가 발생해서 도움을 요청드립니다현재 개발 중인 환경은 윈도우에서 안드로이드 시뮬레이터로 진행 중이며 IDE 는 인텔리제이를 사용하고 있고 gorouter 7.0.1 버전을 사용해서 실습을 하고 있습니다GoRouter 설정 부분은 7.0.1 버전 실습 강좌를 참고해서 변경했고 정상적으로 로그인 및 스플래시 스크린까지 동작을 했습니다.레스토랑 리스트에서 레스토랑 상세화면으로 이동하는 부분을 실습 중 오류가 발생합니다첫번째. context에서 gorouter 관련 메소드가 자동완성이 안되며 실제로 동작도 하지 않습니다.두번째. context.named() ,context.go() 둘 다 아래와 같은 오류가 나타납니다 레스토랑 스크린import 'package:actual/common/component/pagination_list_view.dart'; import 'package:actual/restaurant/component/restaurant_card.dart'; import 'package:actual/restaurant/provider/restaurant_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; // 미사로 나옵니다 class RestaurantScreen extends StatelessWidget { const RestaurantScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return PaginationListView( provider: restaurantProvider, itemBuilder: <RestaurantModel>(context, index, model) { return GestureDetector( onTap: () { context.go("/restaurant/${model.id}"); }, child: RestaurantCard.fromModel(model: model), ); }, ); } } 레스토랑 디테일 스크린import 'package:actual/common/layout/default_layout.dart'; import 'package:actual/common/model/cursor_pagination_model.dart'; import 'package:actual/common/utils/pagination_utils.dart'; import 'package:actual/product/componet/product_card.dart'; import 'package:actual/rating/component/rating_card.dart'; import 'package:actual/rating/model/rating_model.dart'; import 'package:actual/restaurant/component/restaurant_card.dart'; import 'package:actual/restaurant/model/restaurant_detail_model.dart'; import 'package:actual/restaurant/model/restaurant_model.dart'; import 'package:actual/restaurant/provider/restaurant_provider.dart'; import 'package:actual/restaurant/provider/restaurant_rating_provider.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:skeletons/skeletons.dart'; class RestaurantDetailScreen extends ConsumerStatefulWidget { static String get routeName => "restaurantDetail"; final String id; const RestaurantDetailScreen({required this.id, Key? key}) : super(key: key); @override ConsumerState<RestaurantDetailScreen> createState() => _RestaurantDetailScreenState(); } class _RestaurantDetailScreenState extends ConsumerState<RestaurantDetailScreen> { final ScrollController controller = ScrollController(); @override void initState() { super.initState(); ref.read(restaurantProvider.notifier).getDetail(id: widget.id); controller.addListener(listener); } void listener(){ PaginationUtils.paginate(controller: controller, provider: ref.read(restaurantRatingProvider(widget.id).notifier)); } @override Widget build(BuildContext context) { final state = ref.watch(restaurantDetailProvider(widget.id)); final ratingsState = ref.watch(restaurantRatingProvider(widget.id)); print(ratingsState); if (state == null) { return DefaultLayout( child: Center( child: CircularProgressIndicator(), ), ); } return DefaultLayout( title: "제목", child: CustomScrollView( controller: controller, slivers: [ renderTop( model: state, ), if (state is! RestaurantDetailModel) renderLoading(), if (state is RestaurantDetailModel) renderLabel(), if (state is RestaurantDetailModel) renderProducts(products: state.products), if (ratingsState is CursorPagination<RatingModel>) renderRatings( models: ratingsState.data, ), ], ), ); } SliverToBoxAdapter renderTop({ required RestaurantModel model, }) { // 일반 위젯 넣기 return SliverToBoxAdapter( child: RestaurantCard.fromModel(model: model, isDetail: true), ); } SliverPadding renderRatings({ required List<RatingModel> models, }) { return SliverPadding( padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), sliver: SliverList( delegate: SliverChildBuilderDelegate( (_, index) => Padding( padding: const EdgeInsets.only(bottom: 16.0), child: RatingCard.fromModel( model: models[index], ), ), childCount: models.length, ), ), ); } 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, ), ), ), ), ), ), ); } SliverPadding renderLabel() { return SliverPadding( padding: EdgeInsets.symmetric(horizontal: 16.0), sliver: SliverToBoxAdapter( child: Text( "메뉴", style: TextStyle( fontSize: 18.0, fontWeight: FontWeight.w500, ), ), ), ); } SliverPadding renderProducts({ 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.fromRestaurantProductModel(model: model), ); }, childCount: products.length, ), ), ); } } 라우터 설정부분 (auth_provider.dart)List<GoRoute> get routes => [ GoRoute( path: "/", name: RootTab.routeName, builder: (_, state) => RootTab(), routes: [ GoRoute( path: "restaurant/:rid", name: RestaurantDetailScreen.routeName, builder: (_, state) => RestaurantDetailScreen( id: state.pathParameters['rid']!, ), ), ], ), GoRoute( path: "/splash", name: SplashScreen.routeName, builder: (_, state) => SplashScreen(), ), GoRoute( path: "/login", name: LoginScreen.routeName, builder: (_, state) => LoginScreen(), ), ]; 메인import 'package:actual/common/provider/go_router.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; void main() { runApp( ProviderScope( child: _App(), ), ); } class _App extends ConsumerWidget { const _App({Key? key}) : super(key: key); // 라우팅시 BuildContext 사용하기 위한 구조 @override Widget build(BuildContext context, WidgetRef ref) { final router = ref.watch(routerProvider); return MaterialApp.router( theme: ThemeData( fontFamily: "NotoSans", ), debugShowCheckedModeBanner: false, routerConfig: router, ); } } 라우트 프로바이더 (go_router. dart)import 'package:actual/user/provider/auth_provider.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; final routerProvider = Provider<GoRouter>((ref) { final provider = ref.read(authProvider); return GoRouter( routes: provider.routes, initialLocation: "/splash", refreshListenable: provider, redirect: (context, state) { return provider.redirectLogic(state); }, ); }); 오류 로그======== Exception caught by gesture =============================================================== The following NoSuchMethodError was thrown while handling a gesture: Class 'ConsumerStatefulElement' has no instance method 'go'. Receiver: Instance of 'ConsumerStatefulElement' Tried calling: go("/restaurant/5ac83bfb-f2b5-55f4-be3c-564be3f01a5b") When the exception was thrown, this was the stack: #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5) #1 RestaurantScreen.build.<anonymous closure>.<anonymous closure> (package:actual/restaurant/view/restaurant_screen.dart:17:21) #2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:275:24) #3 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:654:11) #4 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:311:5) #5 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:281:7) #6 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:167:27) #7 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:469:20) #8 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:445:22) #9 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:331:11) #10 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:400:7) #11 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:363:5) #12 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:320:7) #13 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:293:9) #14 _invoke1 (dart:ui/hooks.dart:158:13) #15 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:382:7) #16 _dispatchPointerDataPacket (dart:ui/hooks.dart:91:31) Handler: "onTap" Recognizer: TapGestureRecognizer#cc27d debugOwner: GestureDetector state: ready won arena finalPosition: Offset(158.8, 246.5) finalLocalPosition: Offset(142.8, 190.5) button: 1 sent tap down ==================================================================================================== F/crash_dump32(30915): crash_dump.cpp:474] failed to attach to thread 188: Permission denied
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
GoRouter 프로젝트에 적용 후 질문있습니다
GoRouter 적용하는 강의 후 처음 splash screen으로 진입 후 getMe함수를 통해 state가 null이 되는 로직을 통과했음에도 router의 redirect를 따르지 않고 계속해서 splash screen에서 머무는 모습이 나타납니다. print로 결과를 확인해보니 처음 redirect 로직을 검증할 때 UserModelLoading의 Instance로 나타나고 이후 getMe를 통해 null이 되더라도 새롭게 redirection이 일어나지 않는 것 같습니다. 고민하다가 해결책이 떠오르지 않아 문의남깁니다!
-
미해결[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
안녕하세요 InputDecoration() 의 border, enabledBorder, focusedBorder 에 대해서 질문있습니다
border: baseBorder 로 설정했을때 color 를 Colors.red 로 해놔도 아무 변화가 없습니다.enabledBorder: baseBorder 설정했을때 그제서야 빨간색이 적용됩니다. focusedBorder 는 커서가 있을때 border 의 형태로 이해가 되었는데 일반 border 와 enabledBorder 속성은 어떤차이가 있는걸까요? border 속성만 사용할때는 아무 변화가 없는 이유도 궁굼합니다.
-
해결됨[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!
Sec 9. 5번째 강의 1분 대 Provider를 Code generation으로 어떻게 고칠 수 있을까요?
안녕하세요. 실험적으로 Code Generator 기능을 이용해서 프로바이더를 다시 작성해보고 있습니다.궁금한 게 Section 9. 다섯 번째 강의를 보는데, 1분 대에 나오는 RestaurantStateNotifier와 StateNotifierProvider를 어떻게 CodeGenerator를 이용해서 고칠 수 있을까 고민 중입니다. 시도한 코드는 아래와 같은데요(import는 생략했습니다):part 'restaurant_provider.g.dart'; @Riverpod(keepAlive: true) class Restaurant extends _$Restaurant { final RestaurantRepository repository; Restaurant({ required this.repository, }) { paginate(); } // 초기 상태는 Loading 상태로 @override CursorPaginationBase build() { return CursorPaginationLoading(); } paginate() async { final response = await repository.paginate(); state = response; } } 코드 제너레이션은 잘 되는데, 문제는 이를 실행시키려고 하니 다음과 같은 에러가 뜹니다. Launching lib/main.dart on iPhone 14 Pro Max in debug mode... main.dart:1Xcode build done. 3.9sFailed to build iOS appError (Xcode): lib/restaurant/provider/restaurant_provider.g.dart:15:3: Error: The argument type 'Restaurant Function({RestaurantRepository repository})' can't be assigned to the parameter type 'Restaurant Function()' because 'Restaurant Function({RestaurantRepository repository})' is nullable and 'Restaurant Function()' isn't. restaurant_provider.g.dart:15Could not build the application for the simulator.Error launching application on iPhone 14 Pro Max.Exited 이전까지는 잘 됐었는데, 바로 직전 강의에서 CursorPaginationBase를 만들고, 이를 상속받는 CursorPagination 상태들을 구현하고 나서부터, 문제가 발생한 것 같습니다.아마 CursorPagination의 경우는 data와 meta라는 필드가 들어가는데, 어디선가 Code generation에 문제가 생겨서, CursorPaginationBase가 아닌, data와 Meta를 필요로 하는 생성자가 호출된 건 아닌가 의심하는 중입니다. 아래는 위 코드로 생성된 .g.dart 파일입니다. // GENERATED CODE - DO NOT MODIFY BY HAND part of 'restaurant_provider.dart'; // ************************************************************************** // RiverpodGenerator // ************************************************************************** String _$restaurantHash() => r'50915edab0a63433f5d54b932240cf504147e391'; /// See also [Restaurant]. @ProviderFor(Restaurant) final restaurantProvider = NotifierProvider<Restaurant, CursorPaginationBase>.internal( Restaurant.new, name: r'restaurantProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') ? null : _$restaurantHash, dependencies: null, allTransitiveDependencies: null, ); typedef _$Restaurant = Notifier<CursorPaginationBase>; // ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions 어떻게 하면 Code Generator를 이용해서 문제를 해결할 수 있을까요?