Flutter:如何强制应用程序重启(在生产模式下)?
Posted
技术标签:
【中文标题】Flutter:如何强制应用程序重启(在生产模式下)?【英文标题】:Flutter: how to force an application restart (in production mode)? 【发布时间】:2018-10-11 10:08:14 【问题描述】:在生产模式中,有没有办法强制完全重启应用程序(我不是在谈论开发时的热重载!)。
实际用例:
在初始化过程中,应用程序检测到没有网络连接。缺少网络连接可能会阻止正确启动(例如,加载 JSON 文件等外部资源...)。
在初始握手期间,需要下载一些重要资源的新版本(一种更新)。
在这两个用例中,我希望应用程序继续完全重启,而不是在 ApplicationState 级别构建复杂的逻辑。
非常感谢您的提示。
【问题讨论】:
【参考方案1】:您可以将整个应用程序包装到一个有状态的小部件中。当你想重新启动你的应用程序时,用一个拥有不同Key
的孩子重建那个有状态的小部件。
这会让你失去应用的整个状态。
import 'package:flutter/material.dart';
void main()
runApp(
RestartWidget(
child: MaterialApp(),
),
);
class RestartWidget extends StatefulWidget
RestartWidget(this.child);
final Widget child;
static void restartApp(BuildContext context)
context.findAncestorStateOfType<_RestartWidgetState>().restartApp();
@override
_RestartWidgetState createState() => _RestartWidgetState();
class _RestartWidgetState extends State<RestartWidget>
Key key = UniqueKey();
void restartApp()
setState(()
key = UniqueKey();
);
@override
Widget build(BuildContext context)
return KeyedSubtree(
key: key,
child: widget.child,
);
在此示例中,您可以使用 RestartWidget.restartApp(context)
从任何地方重置您的应用。
【讨论】:
像魅力一样工作。非常感谢。 这不应该是正确的答案,因为它不会在操作系统级别“重新启动应用程序”。例如,由于操作系统内存问题,您可能需要执行此操作,并且要清除它,只有从内存中完全删除应用程序并重新启动它会有所帮助。我已经看到了可以在 Manifest 中的 android 级别上完成此操作的示例。谷歌一下。 @JamesGardiner 那么你对这个问题的解决方案是什么? 上述关于 Flutter 1.12.1 弃用的评论需要根据 [***.com/questions/59448102/…final _RestartWidgetState state = context.findAncestorStateOfType<State<RestartWidget>>();
更改为final _RestartWidgetState state = context.findAncestorStateOfType<State<RestartWidget>>();
它对我很有用。但是我在 MaterialApp() 中添加了navigatorKey
,它停止工作。有什么建议?我使用navigatorKey
在没有上下文的情况下推送屏幕。【参考方案2】:
flutter_phoenix package 基于Rémi Rousselet's answer,使其更加简单。
void main()
runApp(
Phoenix(
child: App(),
),
);
然后当你需要重启应用时,只需调用:
Phoenix.rebirth(context);
【讨论】:
我试过这个包,但它对我不起作用,对象不会重置。还是它没有重置对象? 对我不起作用,当我调用 rebirth() 方法时没有任何反应 不再工作github.com/mobiten/flutter_phoenix/issues/20【参考方案3】:我开发了restart_app 插件来本地重启整个应用程序。
更新:
对于遇到此异常的任何人:
MissingPluginException(No implementation found for method restartApp on channel restart)
只需停止并重建应用程序。
【讨论】:
MissingPluginException(No implementation found for method restartApp on channel restart) 是因为 Flutter 2(我尝试在 1.22.6 上使用它)还是其他原因? 请将其迁移到空安全,这是一个非常有用的插件 你碰巧知道linux的解决方案吗? 但它是否适用于 ios 设备 很棒的包装。为我的 Flutter Web 工作【参考方案4】:你也可以使用 runApp(new MyWidget) 函数来做类似的事情
这就是这个函数的作用:
给给定的小部件充气并将其附加到屏幕上。
小部件在布局期间被赋予强制它填满整个屏幕的约束。如果您希望将小部件与屏幕的一侧(例如顶部)对齐,请考虑使用对齐小部件。如果你希望你的小部件居中,你也可以使用中心小部件
再次调用 runApp 将从屏幕上分离前一个根小部件并将给定的小部件附加到它的位置。将新的小部件树与之前的小部件树进行比较,并将任何差异应用于底层渲染树,类似于在调用 State.setState 后重建 StatefulWidget 时发生的情况。
https://docs.flutter.io/flutter/widgets/runApp.html
【讨论】:
这样做的问题是它可能会保留状态 @RémiRousselet 那么你对这个问题的解决方案是什么? 嘿@RémiRousselet,我目前正在使用这种方法和范围块模式。你能帮我理解什么时候可以保留状态吗?祝贺 I/O 公告。 如果您为传递给runApp
的小部件指定UniqueKey
,那应该没问题。更糟糕的是它让想要刷新的小部件知道太多。
这不起作用。再次调用 runapp 完全没有任何作用。【参考方案5】:
这么简单package:flutter_restart
dependencies:
flutter_restart: ^0.0.3
使用:
void _restartApp() async
FlutterRestart.restartApp();
【讨论】:
@PålBrattberg 我在我的项目中使用它并且工作正常。 对那条笼统的评论感到抱歉。我在 iOS、Android、Web 和 macOS 上运行,并在 macOS 上尝试了它不起作用。但对于移动设备,这可能会奏效。不过,我会推荐其中一个纯 Flutter 答案,因为它们可能适用于更多平台。【参考方案6】:我发现 Hossein's restart_app 包对于本机重启也非常有用(不仅在 Flutter 级别)。
对于遇到 MissingPluginException 错误的每个人,只需在设备上重新安装应用程序,这意味着热重载将不起作用。该应用程序具有需要在 Android/iOS 应用程序中编译的原生方法。
【讨论】:
谢谢,伙计。我认为您答案中的软件包链接有问题。正确的链接是:pub.dev/packages/restart_app【参考方案7】:我只想添加关于我已经尝试过@Remi 的答案,它在大多数情况下都可以很好地重启应用程序。答案的唯一问题是,如果您广泛地进行导航路线,您可能会进入一个状态,它会给您一个错误,例如,
The method 'restartApp' was called on null
。
要解决此错误,您必须知道上下文并多次使用 Navigator.of(context).pop();
。对我来说,解决方案是走最初的路线。它将从一个新的注入所有状态。在你想重新启动的地方添加这条线。
Navigator.pushNamedAndRemoveUntil(context,'/',(_) => false);
如果您只想重新启动特定的小部件,那么 Remi 解决方案非常棒。不过,感谢雷米的解决方案。它可以帮助我理解 Flutter 中的状态。
【讨论】:
以上是关于Flutter:如何强制应用程序重启(在生产模式下)?的主要内容,如果未能解决你的问题,请参考以下文章