🌟
【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