Riverpod를 이용한 설정화면 구성방법

HyunHo Shin·2023년 6월 4일
0

설정 기능 구현

이번 글에서는 설정값 기능을 앱에 구현하는 법을 공부해 보도록 하겠습니다.

설정값 기능을 추가할 때 고려해야 하는 고려사항은 4가지 입니다:

  • Default 설정 값을 가질 것
  • 유저가 설정 값을 변경하고, 저장할 수 있을 것
  • 이렇게 변경된 설정 값이 앱 전체에 자동으로 적용될것
  • 필요시 다시 Default 값으로 변결할 수 잇을 것

전체 구조 살펴보기

  1. 먼저 Setting 시작값을 Setting_state에 정의합니다. 이를 defaultState라 부르겠습니다.

  2. defualtState를 Controller에 전달합니다. Controller은 전달 받은 State를 토대로, 새로운 State를 만들어 자체적으로 보관합니다. 해당 State를 SettingState라 부르겠습니다. Controller가 변환하고, 전달할 수 있는 값은 오직 SettingState 값 입니다.

  3. UI에 표시되는 Setting값은 Controller의 SettingState로 부터 전달받습니다. 이후 유저의 Interaction에 따라 변화한 Setting값은 controller에 전달됩니다.

  4. Controller는 유저의 반응에 따라 settingState를 새로운 값으로 치환합니다.

이제 실제 코드로 해당 부분을 한번씩 살펴보도록 하겠습니다


Setting State

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,
    );
  }
}
  • 기본 설정값으로 사용되는 Model 클래스 입니다

Controller

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();
  }
}
  • Controller는 SettingState로 부터 State의 초기 설정값을 끌어오고, 이후 State를 Controller 내부에 보관하면서 업데이트 합니다.

실제 UI 코드

UI 코드는 길기 때문에 아래 두 부분만 코드로 살펴보겠습니다.

  • Controller에서 UI로 State를 가져오는 부분
  • UI에서 Controller로 변경된 State를 전달하는 부분

Controller에서 UI로 State를 가져오는 부분

// Controller에서 UI로 state를 가져옵니다. 
final settingsState = ref.watch(settingsControllerProvider);
category = settingsState.category;
final numQuestionsController = useTextEditingController(
      text: settingsState.numQuestions.toString());
difficulty = settingsState.difficulty;

UI에서 Controller로 변경된 State를 전달하는 부분


다른 화면에 Setting값은 어떻게 전달할까?

지금까지의 Code를 이해하셧다면, 세팅값 정보는 Controller에 저장되고 있다는 점을 이해하실 수 있으실 겁니다. 따라서 다른 화면에 Setting값을 전달하려면 Controller을 다른 화면에 전달하면 됩니다.

간단한 예시를 확인하겠습니다.
{:width="200px" height="200px"}

SettingControllerProvider는 Controller를 전달해 주는 Provider입니다.

감사합니다.

profile
관심사가 다양한 사람

0개의 댓글