이번 글에서는 설정값 기능을 앱에 구현하는 법을 공부해 보도록 하겠습니다.
설정값 기능을 추가할 때 고려해야 하는 고려사항은 4가지 입니다:
먼저 Setting 시작값을 Setting_state에 정의합니다. 이를 defaultState라 부르겠습니다.
defualtState를 Controller에 전달합니다. Controller은 전달 받은 State를 토대로, 새로운 State를 만들어 자체적으로 보관합니다. 해당 State를 SettingState라 부르겠습니다. Controller가 변환하고, 전달할 수 있는 값은 오직 SettingState 값 입니다.
UI에 표시되는 Setting값은 Controller의 SettingState로 부터 전달받습니다. 이후 유저의 Interaction에 따라 변화한 Setting값은 controller에 전달됩니다.
Controller는 유저의 반응에 따라 settingState를 새로운 값으로 치환합니다.
이제 실제 코드로 해당 부분을 한번씩 살펴보도록 하겠습니다
import 'package:flutter_quiz_app/common/utils/enums.dart';
import 'package:flutter_quiz_app/features/settings/models/quiz_category.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
class SettingsState {
final int numQuestions;
final QuizCategory category;
final Difficulty difficulty;
const SettingsState({
required this.numQuestions,
required this.category,
required this.difficulty,
});
factory SettingsState.initial() {
return const SettingsState(
numQuestions: 5,
category: QuizCategory(
id: 9, name: 'General Knowledge'), // Random().nextInt(24) + 9,
difficulty: Difficulty.any,
);
}
SettingsState copyWith({
int? numQuestions,
QuizCategory? category,
Difficulty? difficulty,
}) {
return SettingsState(
numQuestions: numQuestions ?? this.numQuestions,
category: category ?? this.category,
difficulty: difficulty ?? this.difficulty,
);
}
}
import 'package:flutter_quiz_app/features/settings/controllers/settings_state.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final settingsControllerProvider =
StateNotifierProvider<SettingsController, SettingsState>((ref) {
return SettingsController();
});
class SettingsController extends StateNotifier<SettingsState> {
// 기본 설정값이 SettingsState.initial()로 호출되어 StateNotifier에 저장됩니다.
// 이렇게 저장된 설정값은 state라는 이름으로 해당 클래스에 저장됩니다.
SettingsController() : super(SettingsState.initial());
void update(SettingsState settingsState) {
state = state.copyWith(
numQuestions: settingsState.numQuestions,
difficulty: settingsState.difficulty,
category: settingsState.category,
);
}
void reset() {
state = SettingsState.initial();
}
}
UI 코드는 길기 때문에 아래 두 부분만 코드로 살펴보겠습니다.
// Controller에서 UI로 state를 가져옵니다.
final settingsState = ref.watch(settingsControllerProvider);
category = settingsState.category;
final numQuestionsController = useTextEditingController(
text: settingsState.numQuestions.toString());
difficulty = settingsState.difficulty;
지금까지의 Code를 이해하셧다면, 세팅값 정보는 Controller에 저장되고 있다는 점을 이해하실 수 있으실 겁니다. 따라서 다른 화면에 Setting값을 전달하려면 Controller을 다른 화면에 전달하면 됩니다.
간단한 예시를 확인하겠습니다.
{:width="200px" height="200px"}
SettingControllerProvider는 Controller를 전달해 주는 Provider입니다.
감사합니다.