dart 如何重建一个小部件每次到达顶部的路线?

yshpjwxd  于 2024-01-03  发布在  其他
关注(0)|答案(2)|浏览(126)

我有3个小部件A,B,C从A我推B和设置a .然后打印调试消息如果我返回到A(从B)的.然后火灾和消息被打印,但如果从B我推一个替换C,然后返回到A,.然后不火所以所有重建一个小部件每次用户返回到它
内容:在我的测验应用程序,我有一个主屏幕上的按钮,应该只显示,如果用户是在测验(如果他们开始了测验,而不是完成,因为数据保存在设备上),一个恢复按钮,但不仅是恢复按钮应该只显示,如果用户是在测验,但它应该显示一些测验统计数据,如什么学科和所有许多问题等...
所以我需要在用户每次返回时重建主屏幕
我尝试过的:
江荚:尽管我不喜欢这种情况下的解决方案,因为设置一个riverpod的状态意味着我必须同时设置另一整套数据,而且不仅这些数据是扩展的,(一个问题列表,用户当前的问题是什么,用户给出的答案是什么等等)但我也已经保存了测验和平的和平,一个整数在这里当用户去到下一个问题,当用户选择一个答案时,整数上有.但即使尝试使用Riverpod,当返回主屏幕时,主屏幕仍然有过时的信息,因为Riverpod只更新可见的小部件。
navigatorObserver:我尝试使用观察者didPop didPush来检查当前路由是否在顶部,如果是,则调用一个函数,但我甚至无法通过检查部分。

lrl1mhuk

lrl1mhuk1#

在测验屏幕中的WillPopScope上使用(这将处理backButton函数),然后做你想做的事情。

ztmd8pv5

ztmd8pv52#

我使用了一个RouteObserver和一个实现RouteAwaremixin来实现我的目标。
如何做:首先我们需要示例化一个观察者,在我的例子中我使用了一个全局变量。

  1. final routeObserver = RouteObserver<PageRoute>();

字符串
然后传给了MaterialApp中的navigatorObservers

  1. Widget build(BuildContext context) {
  2. return MaterialApp(
  3. (...)
  4. home: const MyHomePage(),
  5. navigatorObservers: [routeObserver],
  6. );
  7. }


有了这个,我创建了一个mixin,它扩展了State(所以我可以使用 context),实现了RouteAware(所以我可以使用它的功能)

  1. mixin RouteAwareMixin<T extends StatefulWidget> on State<T>
  2. implements RouteAware {(...)}


然后我覆盖RouteAware函数以调用函数onActivate和onDeactivate(在下一步中详细介绍)

  1. @override
  2. void didChangeDependencies() {
  3. routeObserver.subscribe(this, ModalRoute.of(context)! as PageRoute);
  4. super.didChangeDependencies();
  5. }
  6. @override
  7. void dispose() {
  8. routeObserver.unsubscribe(this);
  9. super.dispose();
  10. }
  11. @override
  12. void didPopNext() {
  13. onActivate();
  14. }
  15. @override
  16. void didPush() {
  17. onActivate();
  18. }
  19. @override
  20. void didPop() {
  21. onDeactivate();
  22. }
  23. @override
  24. void didPushNext() {
  25. onDeactivate();
  26. }


在这个mixin上,我创建了两个函数,稍后将被使用这个mixin的类覆盖,一个函数用于激活小部件时(小部件获取或重定向到堆栈顶部),另一个函数用于小部件被停用时(从堆栈中弹出一些路由,推到它的顶部)

  1. void onActivate() {
  2. print('MixinActivate: $this');
  3. }
  4. onDeactivate() {
  5. print('MixinDeactivate: $this');
  6. }


在所有的设置中,我只需要在State类上使用这个mixin来获得它的功能。

  1. class _MyHomePageState extends State<MyHomePage> with RouteAwareMixin {
  2. int _counter = 0;
  3. void _incrementCounter() {
  4. setState(() {
  5. _counter++;
  6. });
  7. }
  8. @override
  9. void onActivate() {
  10. _incrementCounter();
  11. super.onActivate();
  12. }
  13. (...)}


我将留下一个完整的演示应用程序显示演示代码,只需创建一个新的应用程序,并替换主.dart内容与下面的。

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(const MyApp());
  3. final routeObserver = RouteObserver<PageRoute>();
  4. class MyApp extends StatelessWidget {
  5. const MyApp({super.key});
  6. static const String _title = 'Flutter RouteAwareMixin';
  7. @override
  8. Widget build(BuildContext context) {
  9. return MaterialApp(
  10. title: _title,
  11. theme: ThemeData(
  12. primarySwatch: Colors.blue,
  13. ),
  14. home: const MyHomePage(),
  15. navigatorObservers: [routeObserver],
  16. );
  17. }
  18. }
  19. class MyHomePage extends StatefulWidget {
  20. const MyHomePage({super.key});
  21. @override
  22. _MyHomePageState createState() => _MyHomePageState();
  23. }
  24. class _MyHomePageState extends State<MyHomePage> with RouteAwareMixin {
  25. int _counter = 0;
  26. void _incrementCounter() {
  27. setState(() {
  28. _counter++;
  29. });
  30. }
  31. @override
  32. void onActivate() {
  33. _incrementCounter();
  34. super.onActivate();
  35. }
  36. @override
  37. Widget build(BuildContext context) {
  38. return Scaffold(
  39. appBar: AppBar(
  40. title: const Text('Flutter AwareMixin'),
  41. ),
  42. body: Center(
  43. child: Column(
  44. mainAxisAlignment: MainAxisAlignment.center,
  45. children: <Widget>[
  46. Text('$_counter'),
  47. SizedBox(
  48. height: 16,
  49. ),
  50. ElevatedButton(
  51. onPressed: () => Navigator.of(context).push(MaterialPageRoute(
  52. builder: (context) => SecondScreen(),
  53. )),
  54. child: Text('OpenSecondScreen'))
  55. ],
  56. ),
  57. ),
  58. );
  59. }
  60. }
  61. class SecondScreen extends StatefulWidget {
  62. const SecondScreen({super.key});
  63. @override
  64. State<SecondScreen> createState() {
  65. return _SecondScreenState();
  66. }
  67. }
  68. class _SecondScreenState extends State<SecondScreen> with RouteAwareMixin {
  69. int _counter = 0;
  70. void _incrementCounter() {
  71. setState(() {
  72. _counter++;
  73. });
  74. }
  75. @override
  76. void onActivate() {
  77. _incrementCounter();
  78. _incrementCounter();
  79. }
  80. @override
  81. Widget build(BuildContext context) {
  82. return Scaffold(
  83. appBar: AppBar(title: Text('SecondScreen')),
  84. body: Center(
  85. child: Column(children: [
  86. Text('SecondScreenCounter: $_counter'),
  87. SizedBox(
  88. height: 16,
  89. ),
  90. ElevatedButton(
  91. onPressed: () =>
  92. Navigator.of(context).pushReplacement(MaterialPageRoute(
  93. builder: (context) => ThirdScreen(),
  94. )),
  95. child: Text('OpenThirdScreen'))
  96. ]),
  97. ),
  98. );
  99. }
  100. }
  101. class ThirdScreen extends StatelessWidget {
  102. const ThirdScreen({super.key});
  103. @override
  104. Widget build(BuildContext context) {
  105. return Scaffold(
  106. appBar: AppBar(title: Text('ThirdScreen')),
  107. );
  108. }
  109. }
  110. mixin RouteAwareMixin<T extends StatefulWidget> on State<T>
  111. implements RouteAware {
  112. @override
  113. void didChangeDependencies() {
  114. routeObserver.subscribe(this, ModalRoute.of(context)! as PageRoute);
  115. super.didChangeDependencies();
  116. }
  117. @override
  118. void dispose() {
  119. routeObserver.unsubscribe(this);
  120. super.dispose();
  121. }
  122. @override
  123. void didPopNext() {
  124. onActivate();
  125. }
  126. @override
  127. void didPush() {
  128. onActivate();
  129. }
  130. @override
  131. void didPop() {
  132. onDeactivate();
  133. }
  134. @override
  135. void didPushNext() {
  136. onDeactivate();
  137. }
  138. void onActivate() {
  139. print('MixinActivate: $this');
  140. }
  141. onDeactivate() {
  142. print('MixinDeactivate: $this');
  143. }
  144. }

展开查看全部

相关问题