상태 관리 패키지(RiverPod) 사용하기
- 하위 위젯에 불필요하게 파라미터 넘겨줄 필요 없어짐(하위 위젯에서 Consumer 쓰면됨)
- 전역 상태 관리 가능(ViewModel 공급을 riverpod이 해주니깐)
- 위젯을 그리는 코드는 Widget에서, 상태 관리는 별도의 클래스에서 하니 유지보수 용이
- 사용법 - ViewModel 만드는 법
1. 관리할 데이터를 담을 상태 클래스를 만든다
class HomeState{
int counter;
HomeState(this.counter);
}
int counter: 클래스의 속성(멤버 변수)으로, 정수형 counter를 선언합니다.
HomeState(this.counter): 이것은 클래스의 생성자입니다.
this는 현재 인스턴스를 가리키는 키워드입니다.
생성자에서 this.counter를 사용하는 이유는 매개변수로 받은 값을 클래스의 counter 속성에 직접 할당하기 위함입니다.
HomeState(int counter) {
this.counter = counter;
}
이는 Dart의 간결한 문법으로, 다음과 같은 일반적인 생성자 코드를 축약한 형태입니다:
이 축약된 문법을 사용하면 코드가 더 간결해지고 가독성이 향상됩니다.
2. Notifier를 상속받는 ViewModel class를 만든다
// Notifier를 상속받으면 상태를 저장하고 업데이트할 수 있는 기능을 갖는다(ViewModel의 구실 가능)
// (Notifier 상속 시 이 ViewModel 이 어떤 상태를 관리하는지 제너릭으로 지정)
class HomeViewModel extends Notifier<HomeState> {
// Notifier 클래스의 build 메서드를 재정의 해서
// 초기 상태값 return 해주기
// => HomeViewModel 이 생성되면 build 메서드의 리턴값으로 상태가 초기화
@override
HomeState build() {
return HomeState(1);
}
void updateState(){
// 상태를 업데이트 해줄 땐 새로운 객체를 만들어 변경
state = HomeState(state.counter + 1);
// 새로운 객체를 state에 할당하지 않으면 자신을 바라보는 View에게
// 상태가 변경되었다고 알리지 않음
// state.coutner++; // => X
}
}
3. 뷰모델을 관리 및 공급해 줄 NotifierProvider 객체를 변수에 담아준다
// 뷰에서는 이 공급자에게 ViewModel 달라고 요청. => 뷰모델 관리자
final homeViewModelProvider
// 이 뷰모델 관리자가 관리해야할 뷰모델의 타입과 뷰모델이 관리하는 상태 제너릭으로 명시
= NotifierProvider<HomeViewModel, HomeState>(
// 생성자에 뷰모델을 생성하는 함수를 넘겨줌
// 뷰에서 관리자에게 뷰모델 달라고 요청할 때 실행되어 뷰모델이 생성됨
// 단 기존에 생성이 되어있으면 기존에 생성된걸 전달
(){
return HomeViewModel();
});
- 사용법 - Widget에서 사용법
Consumer 위젯을 사용해 ViewModel에 접근
뷰모델 관리자에게 뷰모델 혹은 상태를 달라고 요청하기 위해서 WidgetRef가 필요하기 때문
Consumer(
builder: (context, ref, child){
// 상태 사용 할 때
// 1. ref.read(homeViewModelProvider) : 상태 1회성으로 읽고 변경은 감지 X
// 2. ref.watch(homeViewModelProvider) :
// 상태변경 감지해서 상태 변경 일어날때마다 재빌드
// 뷰모델에 접근할 때
// ref.read(homeViewModelProvider.notifier)
ref.watch(homeViewModelProvider);
return Column(children:[
Text()
]);
}
)
Consumer 위젯을 사용하여 ViewModel에 접근할 때, ref.read()와 ref.watch()는 서로 다른 목적으로 사용됩니다. 두 케이스에 대해 자세히 설명하겠습니다:
1. ref.read(homeViewModelProvider)
이 방법은 상태를 1회성으로 읽을 때 사용합니다.
용도: 상태의 현재 값을 한 번만 읽어야 할 때 사용합니다.
동작: 프로바이더의 현재 상태 값을 반환하지만, 이후 상태 변경을 감지하지 않습니다.
적용 사례:
버튼 클릭 이벤트 핸들러 내에서 현재 상태 값을 읽을 때
초기화 로직에서 한 번만 상태를 확인해야 할 때
주의사항: 빌드 메서드 내에서 직접 read를 사용하면 안 됩니다. 상태 변경 시 위젯이 업데이트되지 않기 때문입니다.
2. ref.watch(homeViewModelProvider)
이 방법은 상태 변경을 지속적으로 감지하고 싶을 때 사용합니다.
용도: 상태 변경을 실시간으로 감지하고 UI를 업데이트해야 할 때 사용합니다.
동작: 프로바이더의 현재 상태 값을 반환하고, 이후 상태가 변경될 때마다 위젯을 재빌드합니다.
적용 사례:
텍스트 필드에 현재 상태 값을 표시하고 실시간으로 업데이트해야 할 때
리스트 뷰에서 상태 변경에 따라 항목을 동적으로 표시해야 할 때
장점: 상태 변경에 따라 UI가 자동으로 업데이트되어 일관성을 유지할 수 있습니다.
사용 예시
Consumer(
builder: (context, ref, child) {
// 상태 변경을 감지하고 UI를 업데이트
final state = ref.watch(homeViewModelProvider);
return Column(
children: [
Text('현재 카운터 값: ${state.counter}'),
ElevatedButton(
onPressed: () {
// 버튼 클릭 시 1회성으로 상태를 읽고 업데이트
final viewModel = ref.read(homeViewModelProvider.notifier);
viewModel.updateState();
},
child: Text('카운터 증가'),
),
],
);
},
)
이 예시에서 ref.watch는 state.counter 값의 변화를 감지하여 텍스트를 자동으로 업데이트합니다. 반면 버튼의 onPressed 콜백에서는 ref.read를 사용하여 ViewModel에 1회성으로 접근하고 상태를 업데이트합니다
뷰모델 관리자(공급자)가 뷰모델을 제공할 수 있게 최상위 위젯 ProviderScope로 감싸기
void main() {
// 이 앱에서 ViewModel을 RiverPod이 관리하게 해주게 해줌
runApp(const ProviderScope(child: MyApp()));
}
ViewModel 로 사용할 수 있는 Notifier 종류
- Notifier ✅
- 참조하기 시작하면 앱이 종료될 때 까지 유지
- 로그인 시 회원정보 같이 앱 전반적으로 사용되는 상태를 관리할 때 주로 사용
- AutoDisposeNotifier
- 참조하기 시작한 시점부터 처음 참조한 위젯이 화면에서 없어질때 같이 없어짐
- 로그인 페이지 → 회원가입 페이지 → 로그인 페이지로 뒤로가기 → 회원가입 페이지
- 이 경우에 회원가입 입력정보를 초기화 하고 싶을 때
- AutoDisposeFamilyNotifier
- AutoDisposeNotifier 와 동일하나 ViewModel 최소 생성 시 Widget에서 ViewModel에 값을 넘겨서 무언가를 처리하고 싶을 때
- 블로그 목록 페이지 → 블로그 포스트 상세 페이지 로 이동할 때 어떤 블로그 포스트의 정보를 불러오는지 뷰모델에 넘겨주고 싶을 때
- 블로그 포스트 상세 페이지 → 블로그 포스트 상세 페이지(다른글) 로 이동할 때 FamilyNotifier를 사용하지 않으면 기존의 ViewModel을 공급받지만 FamilyNotifier를 사용하면 블로그 글이 다르면 새로운 ViewModel 공급받음
VS Code 단축키 복습
기본 편집
키명령명령 ID
ctrl+X | 행 삭제 (빈 선택) | editor.action.clipboardCutAction |
ctrl+C | 행 복사 (빈 선택) | editor.action.clipboardCopyAction |
ctrl+shift+k | 행 삭제 | editor.action.deleteLines |
ctrl+Enter | 아래에 행 삽입 | editor.action.insertLineAfter |
ctrl+shift+Enter | 위에 행 삽입 | editor.action.insertLineBefore |
alt+Down | 행을 아래로 이동 | editor.action.moveLinesDownAction |
alt+Up | 행을 위로 이동 | editor.action.moveLinesUpAction |
shift+alt+Down | 위에 행 복사 추가 | editor.action.copyLinesDownAction |
shift+alt+Up | 아래에 행 복사 추가 | editor.action.copyLinesUpAction |
ctrl+d | 다음 선택 찾기 | editor.action.addSelectionToNextFindMatch |
ctrl+k ctrl+d | 마지막 선택 항목을 다음 찾기 항목으로 이동 | editor.action.moveSelectionToNextFindMatch |
ctrl+u | 마지막 커서 작업 실행 취소 | cursorUndo |
shift+alt+i | 선택한 각 줄 끝의 커서 삽입 | editor.action.insertCursorAtEndOfEachLineSelected |
ctrl+shift+l | 현재 선택 항목을 모두 선택 | editor.action.selectHighlights |
ctrl+f2 | 현재 단어의 모든 항목 선택 | editor.action.changeAll |
ctrl+i | 현재 행 선택 | expandLineSelection |
ctrl+alt+Down | 커서를 아래에 추가 | editor.action.insertCursorBelow |
ctrl+alt+Up | 커서를 위에 추가 | editor.action.insertCursorAbove |
ctrl+shift+\ | 일치하는 대괄호로 건너 뛰기 | editor.action.jumpToBracket |
ctrl +] | 라인 들여쓰기 | editor.action.indentLines |
ctrl+[ | 라인 내어쓰기 | editor.action.outdentLines |
Home | 행의 시작으로 이동 | cursorHome |
End | 행의 끝으로 이동 | cursorEnd |
ctrl+End | 파일 끝으로 이동 | cursorBottom |
ctrl+Home | 파일 시작으로 이동 | cursorTop |
ctrl+Down | 스크롤 다운 | scrollLineDown |
ctrl+Up | 스크롤 업 | scrollLineUp |
alt+PageDown | 아래로 페이지 스크롤 | scrollPageDown |
alt+PageUp | 페이지 위로 스크롤 | scrollPageUp |
ctrl+shift+[ | 영역 접기 | editor.fold |
ctrl+shift+] | 영역 펼치기 | editor.unfold |
ctrl+k ctrl+[ | 현재 영역 접기 | editor.foldRecursively |
ctrl+k ctrl+] | 현재 영역 펼치기 | editor.unfoldRecursively |
ctrl+k ctrl+0 | 모든 영역 접기 | editor.foldAll |
ctrl+k ctrl+j | 모든 영역 펼치기 | editor.unfoldAll |
ctrl+k ctrl+c | 행 주석 추가 | editor.action.addCommentLine |
ctrl+k ctrl+u | 행 주석 제거 | editor.action.removeCommentLine |
ctrl+/ | 주석 토글 | editor.action.commentLine |
shift+alt+a | 커서위치에 주석 토글 | editor.action.blockComment |
ctrl+f | 찾기 | actions.find |
ctrl+h | 바꾸기 | editor.action.startFindReplaceAction |
f3 | 다음 찾기 | editor.action.nextMatchFindAction |
shift+f3 | 이전 찾기 | editor.action.previousMatchFindAction |
alt+Enter | 모든 일치 항목을 선택 | editor.action.selectAllMatches |
alt+c | 대소 문자 찾기를 토글 | toggleFindCaseSensitive |
alt+r | 정규식 찾기 전환 | toggleFindRegex |
alt+w | 전체 단어 찾기 토글 | toggleFindWholeWord |
ctrl+m | 포커스 설정을 위해 Tab 키 사용 토글 | editor.action.toggleTabFocusMode |
할당되지 않음 | 렌더링 공백을 토글합니다. | toggleRenderWhitespace |
alt+z | 단어 감싸기 토글 | editor.action.toggleWordWrap |
언어 편집
키명령명령 ID
ctrl+스페이스바 | 트리거 제안 | editor.action.triggerSuggest |
ctrl+shift+스페이스바 | 트리거 매개 변수 힌트 | editor.action.triggerParameterHints |
shift+alt+f | 문서 서식 지정 | editor.action.formatDocument |
ctrl+k ctrl+f | 형식 선택 | editor.action.formatSelection |
f12 | 정의로 이동 | editor.action.goToDeclaration |
ctrl+k ctrl+i | 호버 표시 | editor.action.showHover |
alt+f12 | 키워드 정의 | editor.action.previewDeclaration |
ctrl+k f12 | 키워드 정의 우측에 열기 | editor.action.openDeclarationToTheSide |
ctrl+. | 빠른 수정 | editor.action.quickFix |
shift+f12 | 참조 표시 | editor.action.referenceSearch.trigger |
f2 | 심볼 이름 바꾸기 | editor.action.rename |
ctrl+shift+. | 다음 값으로 바꾸기 | editor.action.inPlaceReplace.down |
ctrl+shift+, | 이전 값으로 바꾸기 | editor.action.inPlaceReplace.up |
shift+alt+오른쪽 | 선택 확장 | editor.action.smartSelect.grow |
shift+alt+왼쪽 | 선택 축소 | editor.action.smartSelect.shrink |
ctrl+k ctrl+x | 공백 제거 | editor.action.trimTrailingWhitespace |
ctrl+km | 언어 모드 변경 | workbench.action.editor.changeLanguageMode |
네비게이션
키명령명령 ID
ctrl+t | 모든 기호 표시 | workbench.action.showAllSymbols |
ctrl+g | 행으로 이동 | workbench.action.gotoLine |
ctrl+p | 빠른 열기, 파일로 이동 | workbench.action.quickOpen |
ctrl+shift+o | 기호로 이동 | workbench.action.gotoSymbol |
ctrl+shift+m | 오류 보기 | workbench.actions.view.problems |
f8 | 다음 오류 또는 경고로 이동 | editor.action.marker.next |
shift+f8 | 이전 오류 또는 경고로 이동 | editor.action.marker.prev |
ctrl+shift+p | 모든 명령 표시 | workbench.action.showCommands |
ctrl+shift+Tab | 편집기 기록 탐색 | workbench.action.openPreviousRecentlyUsedEditorInGroup |
alt+왼쪽 | 뒤로 이동 | workbench.action.navigateBack |
alt+오른쪽 | 앞으로 이동 | workbench.action.navigateForward |
에디터/윈도우 관리
키명령명령 ID
ctrl+shift+n | 새창 열기 | workbench.action.newWindow |
ctrl+w | 창 닫기 | workbench.action.closeWindow |
ctrl+f4 | 편집기 닫기 | workbench.action.closeActiveEditor |
ctrl+kf | 폴더 닫기 | workbench.action.closeFolder |
할당되지 않음 | 편집기 그룹 사이주기 | workbench.action.navigateEditorGroups |
ctrl+\ | 편집기 나누기 | workbench.action.splitEditor |
ctrl+1 | 첫번째 편집기 그룹에 초점 맞추기 | workbench.action.focusFirstEditorGroup |
ctrl+2 | 두번째 편집기 그룹에 초점 맞추기 | workbench.action.focusSecondEditorGroup |
ctrl+3 | 세번째 편집기 그룹에 초점 맞추기 | workbench.action.focusThirdEditorGroup |
ctrl+k ctrl+왼쪽 | 왼쪽 편집기 그룹에 초점 맞추기 | workbench.action.focusPreviousGroup |
ctrl+k ctrl+오른쪽 | 오른쪽 편집기 그룹에 초점 맞추기 | workbench.action.focusNextGroup |
ctrl+shift+PageUp | 왼쪽으로 편집기 이동 | workbench.action.moveEditorLeftInGroup |
ctrl+shift+PageDown | 오른쪽으로 편집기 이동 | workbench.action.moveEditorRightInGroup |
ctrl+k 왼쪽 | 활성 편집기 그룹을 왼쪽으로 이동 | workbench.action.moveActiveEditorGroupLeft |
ctrl+k 오른쪽 | 활성 편집기 그룹을 오른쪽으로 이동 | workbench.action.moveActiveEditorGroupRight |
ctrl+alt+오른쪽 | 편집기를 다음 그룹으로 이동 | workbench.action.moveEditorToNextGroup |
ctrl+alt+왼쪽 | 편집기를 이전 그룹으로 이동 | workbench.action.moveEditorToPreviousGroup |
파일 관리
키명령명령 ID
ctrl+n | 새탭 열기 | workbench.action.files.newUntitledFile |
ctrl+o | 파일 열기 | workbench.action.files.openFile |
ctrl+s | 저장 | workbench.action.files.save |
ctrl+ks | 모두 저장 | workbench.action.files.saveAll |
ctrl+shift+s | 다른 이름으로 저장 | workbench.action.files.saveAs |
ctrl+f4 | 닫기 | workbench.action.closeActiveEditor |
할당되지 않음 | 기타 닫기 | workbench.action.closeOtherEditors |
ctrl+kw | 그룹 닫기 | workbench.action.closeEditorsInGroup |
할당되지 않음 | 다른 그룹 닫기 | workbench.action.closeEditorsInOtherGroups |
할당되지 않음 | 왼쪽에서 왼쪽 그룹 닫기 | workbench.action.closeEditorsToTheLeft |
할당되지 않음 | 그룹을 오른쪽으로 닫기 | workbench.action.closeEditorsToTheRight |
ctrl+k ctrl+w | 모두 닫기 | workbench.action.closeAllEditors |
ctrl+shift+t | 닫힌 편집기 다시 열기 | workbench.action.reopenClosedEditor |
ctrl+k Enter | 계속 열기 | workbench.action.keepEditor |
ctrl+Tab | 다음 열기 | workbench.action.openNextRecentlyUsedEditorInGroup |
ctrl+shift+Tab | 이전 열기 | workbench.action.openPreviousRecentlyUsedEditorInGroup |
ctrl+kp | 활성 파일의 경로 복사 | workbench.action.files.copyPathOfActiveFile |
ctrl+kr | 현재 파일 탐색기로 열기 | workbench.action.files.revealActiveFileInWindows |
ctrl+ko | 현재 파일 새 창에 열기 | workbench.action.files.showOpenedFileInNewWindow |
할당되지 않음 | 열린 파일 비교 | workbench.files.action.compareFileWith |
디스플레이
키명령명령 ID
f11 | 전체 화면 토글 | workbench.action.toggleFullScreen |
ctrl+kz | 젠 모드 토글 | workbench.action.toggleZenMode |
Escape Escape | 젠 모드에서 나가기 | workbench.action.exitZenMode |
ctrl+= | 확대 | workbench.action.zoomIn |
ctrl+- | 축소 | workbench.action.zoomOut |
ctrl+Numpad 0 | 재설정 확대 | workbench.action.zoomReset |
ctrl+b | 사이드바 토글 | workbench.action.toggleSidebarVisibility |
ctrl+shift+e | 탐색기 표시 / 포커스 전환 | workbench.view.explorer |
ctrl+shift+f | 검색보기 | workbench.view.search |
ctrl+shift+g | 소스 제어 표시 | workbench.view.scm |
ctrl+shift+d | 디버그 표시 | workbench.view.debug |
ctrl+shift+x | 확장 표시 | workbench.view.extensions |
ctrl+shift+u | 출력 보기 | workbench.action.output.toggleOutput |
ctrl+q | 명령창에서 빠른 열기 | workbench.action.quickOpenView |
ctrl+shift+c | 새 프롬프트 열기 | workbench.action.terminal.openNativeConsole |
ctrl+shift+v | 마크다운 미리보기 토글 | markdown.showPreview |
ctrl+kv | 마크다운 측면에 미리보기 | markdown.showPreviewToSide |
ctrl^+shift+`(~) | 통합 터미널 토글 | workbench.action.terminal.toggleTerminal |
검색
키명령명령 ID
ctrl+shift+f | 검색보기 | workbench.view.search |
ctrl+shift+h | 파일에서 바꾸기 | workbench.action.replaceInFiles |
alt+c | 대 / 소문자 전환 | toggleSearchCaseSensitive |
alt+w | 전체 단어 맞추기 토글 | toggleSearchWholeWord |
alt+r | 정규 표현식 사용 토글 | toggleSearchRegex |
ctrl+shift+j | 검색 세부 사항 전환 | workbench.action.search.toggleQueryDetails |
f4 | 검색 바꾸기 열기 | search.action.focusNextSearchResult |
shift+f4 | 이전 검색 바꾸기 검색 결과 | search.action.focusPreviousSearchResult |
alt+Down | 다음 검색 용어 표시 | search.history.showNext |
alt+Up | 이전 검색 용어 표시 | search.history.showPrevious |
환경 설정
키명령명령 ID
ctrl+, | 사용자 설정 열기 | workbench.action.openGlobalSettings |
할당되지 않음 | 작업 공간 설정 열기 | workbench.action.openWorkspaceSettings |
ctrl+k ctrl+s | 키보드 단축키 열기 | workbench.action.openGlobalKeybindings |
할당되지 않음 | 사용자 스니펫 열기 | workbench.action.openSnippets |
ctrl+k ctrl+t | 색상 테마 선택 | workbench.action.selectTheme |
할당되지 않음 | 디스플레이 언어 구성 | workbench.action.configureLocale |
디버그
키명령명령 ID
f9 | 중단점 토글 | editor.debug.action.toggleBreakpoint |
f5 | 디버그 시작 | workbench.action.debug.start |
f5 | 디버그 확인 | workbench.action.debug.continue |
ctrl+f5 | 시작(디버깅하지 않음) | workbench.action.debug.run |
f6 | 중지 | workbench.action.debug.pause |
f11 | 들어가기 | workbench.action.debug.stepInto |
shift+f11 | 스텝 아웃 | workbench.action.debug.stepOut |
f10 | 스텝 오버 | workbench.action.debug.stepOver |
shift+f5 | 중지 | workbench.action.debug.stop |
ctrl+k ctrl+i | 호버 표시 | editor.debug.action.showDebugHover |
'공부 일기 > TIL' 카테고리의 다른 글
Flutter 창업반 6주차 TIL2 상태 관리 패키지(RiverPod)관련 복습/실습 (0) | 2024.12.03 |
---|---|
Flutter 창업반 6주차 TIL1 - Dart 언어 특수문자 사용법, 동기/비동기 특강 (1) | 2024.12.02 |
Flutter 창업반 5주차 TIL1 - 데이터 통신 기초와 JSON, MVVM 아키텍쳐 (0) | 2024.11.29 |
Flutter 창업반 3주차 TIL2 - 라이브러리 이용, 동기/비동기 (3) | 2024.11.08 |
Flutter 창업반 3주차 TIL1 - 예외처리, 오류 (0) | 2024.11.08 |