颤动:如何强制重启应用程序(在生产模式下)?

boe*_*edi 25 flutter

生产模式中,有没有办法强制完全重启应用程序(我不是在讨论开发时的热重载!).

实际使用案例:

  • 在初始化过程中,应用程序检测到没有网络连接.缺乏网络连接可能阻止了正确的启动(例如加载外部资源,如JSON文件......).

  • 在最初的握手过程中,需要下载一些重要资源的新版本(更新类型).

在这两种用例中,我希望应用程序继续完全重启,而不是必须在ApplicationState级别构建复杂的逻辑.

非常感谢您的提示.

Rém*_*let 45

您可以将整个应用程序包装到statefulwidget中.当你想重启app时,用一个拥有不同的孩子重建那个statefulwidget Key.

这会让你失去你的应用程序的整个状态.

import 'package:flutter/material.dart';

void main() {
  runApp(new RestartWidget(
    child: // new MaterialApp,
  ));
}

class RestartWidget extends StatefulWidget {
  final Widget child;

  RestartWidget({this.child});

  static restartApp(BuildContext context) {
    final _RestartWidgetState state =
        context.ancestorStateOfType(const TypeMatcher<_RestartWidgetState>());
    state.restartApp();
  }

  @override
  _RestartWidgetState createState() => new _RestartWidgetState();
}

class _RestartWidgetState extends State<RestartWidget> {
  Key key = new UniqueKey();

  void restartApp() {
    this.setState(() {
      key = new UniqueKey();
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      key: key,
      child: widget.child,
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,您可以使用从任何位置重置您的应用RestartWidget.restartApp(context).

  • @JamesGardiner那么您对这个问题的解决方案是什么? (4认同)
  • 这对我来说非常有效。但我在 MaterialApp() 中添加了“navigatorKey”,它停止工作。有什么建议么?我使用“navigatorKey”在没有上下文的情况下推送屏幕。 (4认同)
  • 这不应该是正确的答案,因为它不会在操作系统级别“重新启动应用程序”。例如,由于操作系统内存问题,您可能需要执行此操作,并且要清除它,仅从内存中完全删除该应用程序并重新启动它会有所帮助。我已经看到了可以在清单中的android级别上完成此操作的示例。去谷歌上查询。 (3认同)
  • 奇迹般有效。非常感谢。 (2认同)

Ton*_*ony 34

flutter_phoenix包是基于雷米Rousselet的回答,使它更简单。

void main() {
  runApp(
    Phoenix(
      child: App(),
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

然后当您需要重新启动应用程序时,只需调用:

Phoenix.rebirth(context);
Run Code Online (Sandbox Code Playgroud)


Sha*_*que 17

我只想添加关于我已经尝试过@Remi 答案,该答案在大多数情况下都可以很好地重新启动应用程序。答案的唯一问题是,如果您广泛进行导航路线,某些事情可能会进入这样的状态,它会给您一个错误,例如, The method 'restartApp' was called on null。要解决此错误,您必须了解上下文并使用 Navigator.of(context).pop();多次返回。对我来说,解决方案就是走最初的路线。它将注入新的所有状态。您想重新启动的地方只需添加此行即可。

 Navigator.pushNamedAndRemoveUntil(context,'/',(_) => false);
Run Code Online (Sandbox Code Playgroud)

如果您只想重新启动特定的小部件,那么 Remi 解决方案非常棒。不过还是感谢雷米提供的解决方案。它帮助我理解颤振中的状态。


Min*_*rid 8

如此简单的:flutter_restart

dependencies:
flutter_restart: ^0.0.3
Run Code Online (Sandbox Code Playgroud)

使用:

void _restartApp() async {
  FlutterRestart.restartApp();
}
Run Code Online (Sandbox Code Playgroud)


Dam*_*tes 7

从理论上讲,这不是重新启动,但它适用于大多数情况:

// Remove any route in the stack
Navigator.of(context).popUntil((route) => false);

// Add the first route. Note MyApp() would be your first widget to the app.
Navigator.push(
  context,
  CupertinoPageRoute(builder: (context) => const MyApp()),
);
Run Code Online (Sandbox Code Playgroud)


Dav*_*eno 6

您还可以使用 runApp(new MyWidget) 函数来做类似的事情

这是这个函数的作用:

膨胀给定的小部件并将其附加到屏幕上。

小部件在布局期间受到限制,强制它填满整个屏幕。如果您希望将小部件与屏幕的一侧(例如顶部)对齐,请考虑使用“对齐”小部件。如果您希望将小部件居中,您也可以使用中心小部件

再次调用 runApp 将从屏幕上分离先前的根小部件并将给定的小部件附加到其位置。新的小部件树与之前的小部件树进行比较,任何差异都会应用于底层渲染树,类似于 StatefulWidget 在调用 State.setState 后重建时发生的情况。

https://docs.flutter.io/flutter/widgets/runApp.html

  • 问题在于它可能会保留状态 (3认同)
  • 这是行不通的。再次调用 runapp 完全没有任何作用。 (2认同)

Hos*_*our 5

我开发了restart_app插件来本地重启整个应用程序。


更新:

对于任何获得此异常的人:

MissingPluginException(No implementation found for method restartApp on channel restart)
Run Code Online (Sandbox Code Playgroud)

只需停止并重建应用程序。


Fla*_*awn 5

我发现Hossein 的 restart_app包对于本机重启也非常有用(不仅在 Flutter 级别)。

对于遇到 MissingPluginException 错误的每个人,只需在设备上重新安装应用程序,意味着热重载将不起作用。该应用程序具有需要在 Android/iOS 应用程序中编译的本机方法。


小智 5

我想在注销后重新启动我的应用程序。所以我使用了https://pub.dev/packages/flutter_phoenix(flutter phoenix)。这对我有用。

  1. 通过在终端的 flutter 应用程序目录中运行此命令来安装 flutter_phoenix。 $ flutter pub add flutter_phoenix
  2. 将其导入到“main.dart”中。
  3. 将您的根小部件包裹在 Phoenix 中。
     runApp(
    Phoenix(
      child: MyApp()
  ));

Run Code Online (Sandbox Code Playgroud)
  1. 现在,您可以在任何想要重新启动应用程序的地方调用它:- Phoenix.rebirth(context)

注意: flutter_phoenix 不会在操作系统级别重新启动应用程序,它只会在应用程序级别重新启动应用程序。