🌟

【Flutter】Providerからstateが読み込まれない時の対処法(リスタート時)

に公開

なぜ ref.read(bgmPathProvider.notifier) だけだとバグるの?

ref.read(bgmPathProvider.notifier) は Notifierのインスタンスを取得するだけで、状態の読み込みや初期化は自動では行われません。

あなたの AudioPathNotifier のコンストラクタ内でも load() を呼んでいますが、
Flutter/Riverpod の場合、Providerの初期化は画面のビルド直前など遅延で行われることがあるので、
load() の非同期処理が完了する前に状態を使おうとすると、まだ初期状態のまま(空文字など)でバグることがあります。

class GameScreen extends ConsumerStatefulWidget {
  const GameScreen({super.key});

  
  ConsumerState<GameScreen> createState() => _GameScreenState();
}

class _GameScreenState extends ConsumerState<GameScreen> {
  
  void initState() {
    super.initState();
    _initialize();
    _startGame();
  }

  Future<void> _initialize() async {
    await ref.read(skinPathProvider.notifier).load();
    await ref.read(successskinPathProvider.notifier).load();
    await ref.read(failureskinPathProvider.notifier).load();
  }
}
class SkinPathNotifier extends StateNotifier<String> {
  final String prefsKey;

  SkinPathNotifier(this.prefsKey) : super('') {
    load();
  }

  Future<void> load() async {
    final prefs = await SharedPreferences.getInstance();
    debugPrint(prefs.getString(prefsKey));
    final savedPath = prefs.getString(prefsKey);
    if (savedPath != null && savedPath.isNotEmpty) {
      state = savedPath;
    }
    debugPrint('🔄 Loaded $prefsKey => $state');
  }

  Future<void> setSkin(String path) async {
    state = path;
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(prefsKey, path);
    debugPrint('💾 Saved $prefsKey => $path');
  }
}

Discussion