flutter 当再次调用Drawer中显示的同一页时,FutureProvider不会进入加载状态

but5z9lq  于 2023-06-30  发布在  Flutter
关注(0)|答案(1)|浏览(118)

当您点击抽屉中的项目时,它会打开一个名为“FirstPage”的页面。在初始调用期间,由于该页面不存在于Widget树中,FutureProvider将进入Loading模式,并且一旦检索到数据,屏幕就会切换。
但是,当显示FirstPage并且您编写代码从Drawer调用FirstPage时,FutureProvider的数据检索似乎不会运行,这可能是因为FirstPage仍在Widget树中,并且没有获得autoDisposed。
当我尝试在使用Drawer的转换过程中无效时,如果显示了FirstPage,它不会进入加载模式,但数据重新检索确实执行。不,我希望它从AsyncValue的加载重新开始。
下面是最小可重复的示例。我认为在从抽屉多次调用同一页面时想要刷新是一个常见的要求,但我想知道其他人都在做什么。

import 'package:drawer_refresh_sample/drawer.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: const SampleDrawer(),
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Good Morning',
            ),
          ],
        ),
      ),
    );
  }
}
import 'package:drawer_refresh_sample/first_page.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class SampleDrawer extends ConsumerWidget {
  const SampleDrawer({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Drawer(
      child: ListView(
        children: <Widget>[
          ListTile(
            title: const Text("Page 1"),
            trailing: const Icon(Icons.arrow_forward),
            onTap: () {
              Navigator.of(context).pop();
              ref.invalidate(helloProvider);
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => const FirstPage()));
            },
          ),
        ],
      ),
    );
  }
}
import 'package:drawer_refresh_sample/sample_provider.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import 'drawer.dart';

class FirstPage extends ConsumerWidget {
  const FirstPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncHello = ref.watch(helloProvider);
    return asyncHello.when(
        data: (data) => Scaffold(
            appBar: AppBar(
              title: const Text("First Page"),
            ),
            drawer: const SampleDrawer(),
            body: SafeArea(child: Center(child: Text(data)))),
        error: (error, stackTrace) => Text(stackTrace.toString()),
        loading: () => const Center(child: CircularProgressIndicator.adaptive()));
  }
}
import "dart:math";

import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'sample_provider.g.dart';

@riverpod
Future<String> hello(HelloRef ref) {
  return Future<String>.delayed(const Duration(seconds: 2), () {
    return "Hello${Random().nextInt(10)}";
  });
}
yruzcnhs

yruzcnhs1#

根据Riverpod的文档,在进行刷新时,会跳过加载回调。如果您使用的是新版本的Riverpod,您可以将skipLoadingOnRefresh设置为false。

return asyncHello.when(
        skipLoadingOnRefresh: false,
        data: (data) => Scaffold(
            appBar: AppBar(
              title: const Text("First Page"),
            ),
            drawer: const SampleDrawer(),
            body: SafeArea(child: Center(child: Text(data)))),
        error: (error, stackTrace) => Text(stackTrace.toString()),
        loading: () => const Center(child: CircularProgressIndicator.adaptive()));

还有第二种方法。你可以通过检查isRefreshing成员变量来检查它是否正在刷新。例如:

@override
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncHello = ref.watch(helloProvider);
    if(asyncHello.isRefreshing) {
      // return <Loading widget>
    }
    return asyncHello.when(
        data: (data) => Scaffold(
            appBar: AppBar(
              title: const Text("First Page"),
            ),
            drawer: const SampleDrawer(),
            body: SafeArea(child: Center(child: Text(data)))),
        error: (error, stackTrace) => Text(stackTrace.toString()),
        loading: () => const Center(child: CircularProgressIndicator.adaptive()));
  }

相关问题