Flutter 中的 Singleton 给出运行时错误 "Unhandled Exception: Reading static variable '_instance@545324594' during its initialization"
Singleton in Flutter gives runtime error "Unhandled Exception: Reading static variable '_instance@545324594' during its initialization"
我尝试在 Flutter 应用程序(Flutter 版本 1.12.13+hotfix8)中实现 MVP 模式。
我的控制器(演示者)是一个单身人士,看起来像这样:
import 'package:flutter/material.dart';
// local file imports
import 'package:prototype/gui/screens/welcome/welcome.dart';
// this is a singleton
class Controller {
static final Controller _instance = Controller._internal();
Widget _currentWidget;
Controller._internal() {
this._currentWidget = ScreenWelcome();
}
factory Controller() => _instance;
Widget get currentWidget => this._currentWidget;
set currentWidget(Widget widget){
_currentWidget = widget;
}
}
我的主屏幕如下所示:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// local file imports
import 'package:prototype/controller/conroller.dart';
import 'package:prototype/gui/screens/register/register.dart';
import 'package:prototype/gui/screens/register/sign_in.dart';
import 'package:prototype/gui/screens/text_viewer/text_viewer.dart';
class ScreenWelcome extends StatelessWidget {
final _controller = Controller();
@override
Widget build(BuildContext context) {
return Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Image.asset('resources/zombiepaar.jpg',
width: 500, height: 500, fit: BoxFit.fitWidth),
SizedBox(
height: 20.0,
),
RaisedButton(
child: Text("Ein neues Konto erstellen"),
onPressed: () => _controller.currentWidget = ScreenRegister(),
),
SizedBox(
height: 20.0,
),
RaisedButton(
child: Text("Mit bestehendem Konto einloggen"),
onPressed: () => _controller.currentWidget = ScreenSignIn(),
),
SizedBox(
height: 20.0,
),
Row(
children: <Widget>[
GestureDetector(
child: Text(
"Nutzungsbedingungen",
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.blue),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ScreenTextViewer(
title: "Nutzungsbedingungen",
ressourceFileToLoad: 'resources/AGBs.txt'),
)),
),
SizedBox(
width: 20.0,
),
GestureDetector(
child: Text(
"Datenschutzrichtlinien",
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.blue),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ScreenTextViewer(
title: "Nutzungsbedingungen",
ressourceFileToLoad: 'resources/AGBs.txt'),
),
),
),
],
),
],
),
),
);
}
}
但是当我 运行 我的应用程序时,我收到以下运行时错误:
D/FlutterActivityAndFragmentDelegate(21372): Executing Dart entrypoint: main, and sending initial route: /
E/flutter (21372): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Reading static variable '_instance@545324594' during its initialization
E/flutter (21372): #0 Controller._instance (package:prototype/controller/conroller.dart:9:27)
E/flutter (21372): #1 new Controller (package:prototype/controller/conroller.dart:17:27)
E/flutter (21372): #2 new ScreenWelcome (package:prototype/gui/screens/welcome/welcome.dart:11:23)
E/flutter (21372): #3 new Controller._internal (package:prototype/controller/conroller.dart:14:27)
E/flutter (21372): #4 Controller._instance (package:prototype/controller/conroller.dart:9:50)
E/flutter (21372): #5 Controller._instance (package:prototype/controller/conroller.dart:9:27)
E/flutter (21372): #6 new Controller (package:prototype/controller/conroller.dart:17:27)
E/flutter (21372): #7 new MyApp (package:prototype/main.dart:10:22)
E/flutter (21372): #8 main (package:prototype/main.dart:6:23)
E/flutter (21372): #9 _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:239:25)
E/flutter (21372): #10 _rootRun (dart:async/zone.dart:1126:13)
E/flutter (21372): #11 _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (21372): #12 _runZoned (dart:async/zone.dart:1518:10)
E/flutter (21372): #13 runZoned (dart:async/zone.dart:1502:12)
E/flutter (21372): #14 _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:231:5)
E/flutter (21372): #15 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:307:19)
E/flutter (21372): #16 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
知道如何解决这个问题吗?我发现 Google 没有任何帮助,而且我对 dart 和 Flutter 还很陌生。也许我实现单例 class 的方式不对?
编辑:米main.dart文件是
import 'package:flutter/material.dart';
// local file imports
import 'package:prototype/controller/conroller.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of the application.
final controller = Controller(); // presenter in MVP design pattern
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: controller.currentWidget, // controller decides the main widget
);
}
}
最后,我找到了答案:我必须尽可能晚地调用小部件的构造函数。因此,我在getter函数中调用了它。工作代码如下所示:
import 'package:flutter/material.dart';
// local file imports
import 'package:prototype/gui/screens/welcome/welcome.dart';
// this is a singleton
class Controller {
static final Controller _instance = Controller._internal();
Function _currentWidget;
Controller._internal() {
this._currentWidget = () => ScreenWelcome();
}
factory Controller() => _instance;
Widget get currentWidget => this._currentWidget();
set currentWidget(Widget widget){
_currentWidget = () => widget;
}
}
也许有一天它会对某人有所帮助:)
你有循环依赖。 ScreenWelcome
的创建调用 Controller
构造函数,该构造函数读取 _instance
字段,后者构造 Controller
,后者创建 ScreenWelcome
。您很幸运 _instance
字段是惰性的,因为它会及早检测到循环而不是遇到堆栈溢出。
如果您有两个 类 具有必须指向彼此的最终字段。那基本上是不可能的。幸运的是 _currentWidget
不是最终的,所以这是您在创建两个对象后需要设置的那个。
我会这样做:
class Controller {
static final _instance = Controller._();
Widget_currentWidget;
factory Controller() => _instance;
Controller._();
}
class ScreenWelcome {
final Controller _controller;
ScreenWelcome() : _controller = Controller() {
// This is the soonest a reference to this widget is available.
_controller.currentWidget = this;
}
}
我尝试在 Flutter 应用程序(Flutter 版本 1.12.13+hotfix8)中实现 MVP 模式。 我的控制器(演示者)是一个单身人士,看起来像这样:
import 'package:flutter/material.dart';
// local file imports
import 'package:prototype/gui/screens/welcome/welcome.dart';
// this is a singleton
class Controller {
static final Controller _instance = Controller._internal();
Widget _currentWidget;
Controller._internal() {
this._currentWidget = ScreenWelcome();
}
factory Controller() => _instance;
Widget get currentWidget => this._currentWidget;
set currentWidget(Widget widget){
_currentWidget = widget;
}
}
我的主屏幕如下所示:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// local file imports
import 'package:prototype/controller/conroller.dart';
import 'package:prototype/gui/screens/register/register.dart';
import 'package:prototype/gui/screens/register/sign_in.dart';
import 'package:prototype/gui/screens/text_viewer/text_viewer.dart';
class ScreenWelcome extends StatelessWidget {
final _controller = Controller();
@override
Widget build(BuildContext context) {
return Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Image.asset('resources/zombiepaar.jpg',
width: 500, height: 500, fit: BoxFit.fitWidth),
SizedBox(
height: 20.0,
),
RaisedButton(
child: Text("Ein neues Konto erstellen"),
onPressed: () => _controller.currentWidget = ScreenRegister(),
),
SizedBox(
height: 20.0,
),
RaisedButton(
child: Text("Mit bestehendem Konto einloggen"),
onPressed: () => _controller.currentWidget = ScreenSignIn(),
),
SizedBox(
height: 20.0,
),
Row(
children: <Widget>[
GestureDetector(
child: Text(
"Nutzungsbedingungen",
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.blue),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ScreenTextViewer(
title: "Nutzungsbedingungen",
ressourceFileToLoad: 'resources/AGBs.txt'),
)),
),
SizedBox(
width: 20.0,
),
GestureDetector(
child: Text(
"Datenschutzrichtlinien",
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.blue),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ScreenTextViewer(
title: "Nutzungsbedingungen",
ressourceFileToLoad: 'resources/AGBs.txt'),
),
),
),
],
),
],
),
),
);
}
}
但是当我 运行 我的应用程序时,我收到以下运行时错误:
D/FlutterActivityAndFragmentDelegate(21372): Executing Dart entrypoint: main, and sending initial route: /
E/flutter (21372): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Reading static variable '_instance@545324594' during its initialization
E/flutter (21372): #0 Controller._instance (package:prototype/controller/conroller.dart:9:27)
E/flutter (21372): #1 new Controller (package:prototype/controller/conroller.dart:17:27)
E/flutter (21372): #2 new ScreenWelcome (package:prototype/gui/screens/welcome/welcome.dart:11:23)
E/flutter (21372): #3 new Controller._internal (package:prototype/controller/conroller.dart:14:27)
E/flutter (21372): #4 Controller._instance (package:prototype/controller/conroller.dart:9:50)
E/flutter (21372): #5 Controller._instance (package:prototype/controller/conroller.dart:9:27)
E/flutter (21372): #6 new Controller (package:prototype/controller/conroller.dart:17:27)
E/flutter (21372): #7 new MyApp (package:prototype/main.dart:10:22)
E/flutter (21372): #8 main (package:prototype/main.dart:6:23)
E/flutter (21372): #9 _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:239:25)
E/flutter (21372): #10 _rootRun (dart:async/zone.dart:1126:13)
E/flutter (21372): #11 _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (21372): #12 _runZoned (dart:async/zone.dart:1518:10)
E/flutter (21372): #13 runZoned (dart:async/zone.dart:1502:12)
E/flutter (21372): #14 _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:231:5)
E/flutter (21372): #15 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:307:19)
E/flutter (21372): #16 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
知道如何解决这个问题吗?我发现 Google 没有任何帮助,而且我对 dart 和 Flutter 还很陌生。也许我实现单例 class 的方式不对?
编辑:米main.dart文件是
import 'package:flutter/material.dart';
// local file imports
import 'package:prototype/controller/conroller.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of the application.
final controller = Controller(); // presenter in MVP design pattern
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
home: controller.currentWidget, // controller decides the main widget
);
}
}
最后,我找到了答案:我必须尽可能晚地调用小部件的构造函数。因此,我在getter函数中调用了它。工作代码如下所示:
import 'package:flutter/material.dart';
// local file imports
import 'package:prototype/gui/screens/welcome/welcome.dart';
// this is a singleton
class Controller {
static final Controller _instance = Controller._internal();
Function _currentWidget;
Controller._internal() {
this._currentWidget = () => ScreenWelcome();
}
factory Controller() => _instance;
Widget get currentWidget => this._currentWidget();
set currentWidget(Widget widget){
_currentWidget = () => widget;
}
}
也许有一天它会对某人有所帮助:)
你有循环依赖。 ScreenWelcome
的创建调用 Controller
构造函数,该构造函数读取 _instance
字段,后者构造 Controller
,后者创建 ScreenWelcome
。您很幸运 _instance
字段是惰性的,因为它会及早检测到循环而不是遇到堆栈溢出。
如果您有两个 类 具有必须指向彼此的最终字段。那基本上是不可能的。幸运的是 _currentWidget
不是最终的,所以这是您在创建两个对象后需要设置的那个。
我会这样做:
class Controller {
static final _instance = Controller._();
Widget_currentWidget;
factory Controller() => _instance;
Controller._();
}
class ScreenWelcome {
final Controller _controller;
ScreenWelcome() : _controller = Controller() {
// This is the soonest a reference to this widget is available.
_controller.currentWidget = this;
}
}