You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Riverpod StateNotifier状态未更新,求助排查原因

问题:StateNotifier状态更新后UI无响应(Riverpod 1.0.4)

在Riverpod 1.0.4版本中使用自定义状态类结合StateNotifier时,执行StateNotifier内的函数后,函数内部打印显示状态已变更,但UI始终停留在ListInit状态,无任何更新。此前在Riverpod 0.14.0+3版本中相同代码结构可正常运行,已尝试适配1.0.x版本改动,无报错但问题依旧。


状态类与StateNotifier实现

import 'package:finanz_app/models/konten.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';

abstract class ListState {
  const ListState();
}

class ListInit extends ListState {
  const ListInit();
}

class ListLoding extends ListState {
  const ListLoding();
}

class ListLoded extends ListState {
  final List<Konten> konten;
  const ListLoded(this.konten);
}

class ListError extends ListState {
  final String errorMessage;
  const ListError(this.errorMessage);
}

final listNotifierProvider = StateNotifierProvider((ref) {
  return ListStateNotifier();
});

class ListStateNotifier extends StateNotifier<ListState> {
  ListStateNotifier() : super(const ListInit());

  Future<void> getFromDB() async {
    state = const ListLoding();

    final box = Hive.box('konten');

    final List<Konten> kontenData = box.keys.map((key) {
      final Konten value = box.get(key);
      return value;
    }).toList();

    print(kontenData.length);
    state = ListLoded(kontenData);

    print(state.runtimeType);
  }

  Future<void> add(Konten konto) async {
    final box = Hive.box('konten');

    box.add(konto);

    print(state.runtimeType);

    getFromDB();
  }

  Future<void> deletedAll() async {
    final box = Hive.box('konten');

    for (int key in box.keys) {
      box.delete(key);
    }

    getFromDB();
  }
}

UI层Consumer代码

...
body: Consumer(
  builder: (context, ref, child) {
    final state = ref.watch(listNotifierProvider);

    print(state.runtimeType);

    if (state is ListInit) {
      return const Text(
        "InitState",
      );
    } else if (state is ListLoding) {
      return const CircularProgressIndicator();
    } else if (state is ListLoded) {
      return Text(state.konten.length.toString());

    } else if (state is ListError) {
      return Text("ERROR: ${state.errorMessage}");
    } else {
      return const Text("Unknown ERROR");
    }
  },
),
...

ProviderScope配置

@override
Widget build(BuildContext context) {
  return ProviderScope(
    child: MaterialApp(
      ...
      initialRoute: '/',
      routes: {
        "/": (context) => const HomePage(),
      },
    ),
  );
}

解决方案

1. 修复StateNotifierProvider的泛型声明

Riverpod 1.0+版本对StateNotifierProvider的类型推断做了严格限制,必须显式指定泛型参数<StateNotifierType, StateType>,否则UI无法正确监听状态变化。

修改后的Provider定义:

final listNotifierProvider = StateNotifierProvider<ListStateNotifier, ListState>((ref) {
  return ListStateNotifier();
});

2. 确保初始化时调用状态加载方法

检查UI页面是否在初始化时调用了getFromDB方法,比如在initState中:

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    ref.read(listNotifierProvider.notifier).getFromDB();
  });
}

如果没有调用该方法,状态会一直停留在ListInit,自然不会触发UI更新。

3. 检查Hive初始化是否完成

确保在使用Hive之前已经完成初始化,比如在main函数中:

void main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(KontenAdapter()); // 确保注册了Konten的适配器
  await Hive.openBox('konten');
  runApp(const MyApp());
}

内容的提问来源于stack exchange,提问作者Berkkan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 01:55:19