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&lt;State&lt;RestartWidget&gt;&gt;(); 更改为final _RestartWidgetState state = context.findAncestorStateOfType&lt;State&lt;RestartWidget&gt;&gt;(); 它对我很有用。但是我在 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:如何强制应用程序重启(在生产模式下)?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter webview强制暗模式解决方案?

如何在 Windows 中以编程方式强制重启/重新加载 Playback 设备?

如何让安卓手机强制4G网络模式

在 Flutter 中强制纵向方向时出错

如何强制 Flutter 使用新的开发者证书?

Android:如何在“强制关闭”后自动重启应用程序?