flutter Riverpood在我进入屏幕之前不会更新状态

6rqinv9w  于 2023-01-31  发布在  Flutter
关注(0)|答案(1)|浏览(117)

我有一个常规配置屏幕,其中有一个同步数据的按钮

(...)
appBar: AppBar(
        actions: [
          Row(
            children: [
              const Text(ConfigurationsStringsUI.updateGeneral),
              IconButton(
                icon: const Icon(Icons.sync),
                onPressed: () {
                  ref.read(listProductController.notifier).syncProducts();
                  ref.read(listEmployedController.notifier).syncEmployees();
                },
              ),
            ],
          )
        ],
      ),
(...)

在产品的情况下,它有一个特定的屏幕,负责管理他们,基本上是一个CRUD。当我按下同步按钮,想法是连接到supabase和更新数据。而这是发生显示一个加载。问题是,加载不出现。products_page.dart

GetIt sl = GetIt.instance;

class CRUDProduct extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(
          leading: IconButton(
            icon: const Icon(Icons.arrow_back),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
          actions: [
            IconButton(
              onPressed: () {
                ref.read(listProductController.notifier).syncProducts();
              },
              icon: const Icon(Icons.update),
            )
          ],
        ),
        floatingActionButton: ref.watch(isVisibleFabProducts)
            ? FloatingActionButton(
                onPressed: () {
                  showDialog(
                    context: scaffoldKey.currentContext!,
                    builder: (context) => AddProductDialog(),
                  );
                },
                child: const Icon(Icons.fastfood),
              )
            : null,
        body: ref.watch(listProductController).when(
          data: (products) {
            if (products.isEmpty) {
              return const Center(
                child: Text(ProductStringsUI.emptyList),
              );
            } else {
              return NotificationListener<UserScrollNotification>(
                onNotification: (notification) {
                  if (notification.direction == ScrollDirection.forward) {
                    ref.read(isVisibleFabProducts.notifier).state = true;
                  }
                  if (notification.direction == ScrollDirection.reverse) {
                    ref.read(isVisibleFabProducts.notifier).state = false;
                  }
                  return true;
                },
                child: ListView.separated(
                    shrinkWrap: true,
                    itemBuilder: (context, index) {
                      return ItemProductList(product: products[index]);
                    },
                    separatorBuilder: (_, __) => const Divider(
                          color: Colors.grey,
                        ),
                    itemCount: products.length),
              );
            }
          },
          error: (error, stackTrace) {
            return const Center(
              child: Text(ProductStringsUI.errorList),
            );
          },
          loading: () {
            return const Center(child: CircularProgressIndicator());
          },
        ));
  }
}

产品供应商:

final listProductController =
    StateNotifierProvider<ProductController, AsyncValue<List<LocalProduct>>>(
        (ref) => ProductController(ref));

产品控制器dart

class ProductController extends StateNotifier<AsyncValue<List<LocalProduct>>> {
  ProductController(this._ref) : super(const AsyncValue.loading()) {
    getProducts();
  }
  final Ref _ref;

  Future<void> getProducts() async {
    try {
      final employees = await sl.get<ListProductUseCase>().getProducts();

      if (mounted) {
        state = AsyncValue.data(employees);
      }
    } catch (e) {
      state = AsyncValue.error(e, StackTrace.current);
    }
  }

  Future<void> syncProducts() async {
    try {
      _ref.read(listCategoryController.notifier).state =
          const AsyncValue.loading();
      _ref.read(listEmployedController.notifier).state =
          const AsyncValue.loading();
      state = const AsyncValue.loading();
      await _ref.read(listCategoryController.notifier).syncCategory();
      final employees = await sl.get<SyncProductUseCase>().syncProducts();
      state.whenData((value) {
        if (mounted) {
          state = AsyncValue.data([...value, ...employees]);
        }
      });
      _ref.invalidate(listProductController);
    } catch (e) {
      state = AsyncValue.error(e, StackTrace.current);
    }
  }
  }

在产品的情况下,它有一个特定的屏幕负责管理它们,基本上是一个CRUD。当我按下同步按钮时,想法是连接到supabase并更新数据。当这发生时显示一个loadign。问题是加载没有出现。有两种情况:
1-我打开应用程序,我按下配置屏幕上的同步按钮,我进入负责管理产品的屏幕,我看到加载的产品,并在这一刻它更新我的新数据,当我应该看到加载,然后新的数据。在这种情况下,我最大的怀疑奇怪的行为是。
2-我打开应用程序,我进入负责管理产品的屏幕,我进入配置屏幕,我按下同步,在这种情况下,如果我进入如果加载出现
员工也是如此。

ivqmmu1c

ivqmmu1c1#

当您在Riverpod中有一个异步提供程序时,您应该告诉它加载:

Future<void> addTopic(String name) async {
state = const AsyncValue.loading(); // Here

state = await AsyncValue.guard(() async { // And then you guard the value

  // Inside the brackets do all the logic of the function
  final currentId = ref.watch(currentSubjectProvider);
  final topicRepo = ref.watch(topicRepoProvider);

  await topicRepo.addTopic(currentId!, name);
  return _getTopics();
});
}

我的这个例子,是一真实的项目,我正在工作,这是加载预期,但我应该提到,我使用的是Riverpod发电机,所以如果发电机做了什么,我不知道它。
如果将状态设置为正在加载并保护值,则该提供程序的所有列表器都应该正确加载。

相关问题