我正在尝试使用Flutter / Dart。但是当从另一个类访问时,我的静态变量会不断重新初始化。
我有一个类,在其单独的dart源文件中,保存服务器状态,声明如下:
class ServerStatus{
static int newestBinary;
static bool serverUp;
}
我通过
初始化了他们@main()
ServerStatus.newestBinary = 20;
ServerStatus.serverUp = true;
。之后,当我尝试在我的应用程序中的另一个页面上访问它们时,变量“newestBinary
”和“serverUp
”都变为null
,就像它们被重新启用一样。 (如果我将它们声明为static int newestBinary = 10;
,然后在ServerStatus.newestBinary = 20;
重新分配main()
,它仍将在我的应用中的另一个页面显示为10。
我的应用程序没有在两个操作之间退出或停止。在什么情况下,静态变量会被重新激活?
如果我必须为应用程序保存全局和常用信息,那么除了使用静态变量之外,最好的方法是什么呢?
提前致谢。
答案 0 :(得分:12)
我玩弄了一个小时,意识到这似乎是什么原因。显然我在做的时候:
import 'package:flutter_test_app/main.dart';
与
不同import 'main.dart';
即使两个源文件属于同一个包。
所以最后我的测试代码如下:
main.dart:
import 'package:flutter/material.dart';
import 'pageA.dart';
import 'pageB.dart';
import 'pageH.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
static bool testFlag = false;
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
testFlag = true;
ThemeData mainTheme = new ThemeData(
primarySwatch: Colors.cyan,
);
print("testFlag @ MyApp: " + testFlag.toString());
MaterialApp mainApp = new MaterialApp(
title: 'Instabazaar',
theme: mainTheme,
home: new HomePage(title: 'Instabazaar'),
);
return mainApp;
}
}
class HomePage extends StatefulWidget {
final String title;
HomePage({Key key, this.title}) : super(key: key);
@override
_HomePageState createState() {
return new _HomePageState();
}
}
class _HomePageState extends State<HomePage> {
int _currentPageID = 0; // 0=home, 1=pageA, 2=pageB
@override
Widget build(BuildContext context) {
print("testFlag @ HomePage: " + MyApp.testFlag.toString());
AppBar appBar = new AppBar(
title: new Text("TestApp"),
centerTitle: true,
);
BottomNavigationBar bottomNavigationBar = new BottomNavigationBar(
type: BottomNavigationBarType.shifting,
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(icon: new Icon(Icons.home), title: new Text('Home'), backgroundColor: Theme.of(context).accentColor),
new BottomNavigationBarItem(icon: new Icon(Icons.explore), title: new Text('PageA'), backgroundColor: Colors.purple),
new BottomNavigationBarItem(icon: new Icon(Icons.star), title: new Text('PageB'), backgroundColor: Colors.redAccent),
],
onTap: (i) => setState( () => _currentPageID = i ),
currentIndex: _currentPageID
);
Scaffold mainScaffold = new Scaffold(
appBar: appBar,
body: _getNewSubPage(),
bottomNavigationBar: bottomNavigationBar,
);
return mainScaffold;
}
//MARK: navigation
Widget _getNewSubPage(){
switch (_currentPageID)
{
case 1:
return new pageA();
case 2:
return new pageB();
default:
return new pageH();
}
}
}
pageA.dart / pageB.dart:
import 'package:flutter/material.dart';
import 'package:flutter_test_app/main.dart';
class pageA extends StatefulWidget{
pageAState createState() => new pageAState();
}
class pageAState extends State<pageA> {
@override
Widget build(BuildContext context) {
print("testFlag @ pageA: " + MyApp.testFlag.toString());
return new Container();
}
}
pageH.dart:
import 'package:flutter/material.dart';
import 'main.dart';
class pageH extends StatefulWidget{
pageHState createState() => new pageHState();
}
class pageHState extends State<pageH> {
@override
Widget build(BuildContext context) {
print("testFlag @ pageH: " + MyApp.testFlag.toString());
return new Container();
}
}
唯一的区别是import语句。但是,对于pageA / pageB,print语句将给出“false”。至于pageH,print语句将给出“true”。我已经切换了import语句并检查出来。我不熟悉dart实际上如何解释代码,所以我不确定它是一个飞镖的东西,一个设置的东西或一个颤动的东西。我会继续调查,但现在我的问题已经解决了。
感谢大家的帮助。
答案 1 :(得分:6)
如果导入以:&#34; package:your_app_package / file.dart&#34;。
开头,Flutter和Dart似乎有问题为静态(全局)变量找到相同的实例。因此,假设您希望在main.dart文件中拥有静态变量(myStaticVariable),您可以在其中拥有MyApp类。并且假设您希望通过使用MyApp.myStaticVariable调用项目中某个不同的.dart文件中的静态变量。
在这种情况下,如果您使用&#34; import package导入main.dart:your_app_package / main.dart&#34;变量将具有&#34; null&#34;价值,即使它之前已经初始化了!
如果您使用&#34; import main.dart&#34;导入main.dart。 (如果文件在同一目录中)或&#34; import ../main.dart" (如果你的文件是一个目录dipper然后是main.dart),你将得到MyApp.myStaticVariable的正确值。
我不知道为什么会这样,但也许像@Kevin Moore提到的那样,有一个问题,Flutter团队需要解决它。
答案 2 :(得分:2)
一个已知问题是入口点文件(lib/main.dart
)不得包含相对导入。
如果所有导入都以
开头import 'dart:...';
import 'package:my_project/...'
然后可以避免这个问题。
这是因为Flutter没有完全遵循其中入口点文件在lib/
之外的pub包约定(例如bin/
,web/
,tool/
,{{ 1}},或test/
)。
另见https://github.com/flutter/flutter/issues/15748
更新2018-10-17
此问题已在Dart中修复,但可能尚未在所有Flutter频道中登陆。
答案 3 :(得分:1)
您可以直接将静态变量初始化为声明。 这样的事情会更好:
class ServerStatus{
static int newestBinary = 20;
static bool serverUp = false;
}
此外,您确定您的分配是否正确执行,之前还有其他什么?没有更多的代码,就很难给出完整的答案。
另一个原因可能是您如何进行分配。
你在做newestBinary = 20;
还是ServerStatus.newestBinary = 20;
?
静态变量与全局变量不同。如果执行newestBinary = 20;
,则不会更改ServerStatus的静态变量,而是更改局部变量。
答案 4 :(得分:0)
在我的应用程序中,我必须从xml源读取内容并在应用程序的许多部分中使用它。我想在应用程序启动时加载一次内容。
类BrandsCollection
的静态对象是完美的解决方案,但是从某些类中它是null。
我尝试改变其他用户写的路径,但它仍无法在任何地方工作,所以我使用了这个简单的解决方案:
class GlobalData {
//this is what I need to have in many parts of my app
static BrandsCollection brandsCollection;
}
void main() {
XmlDataReader dataReader = new XmlDataReader();
dataReader.loadContent().then((content) {
//After reading the xml file, I create the instance
GlobalData.brandsCollection = new BrandsCollection(content);
//I run the app only when the object is initialized
runApp(new MyApp());
});
}
import '../main.dart';
class A {
A(){
BrandsCollection _brandsCollection = GlobalData.brandsCollection;
_brandsCollection.foo();
}
}
我创建了相同的静态变量:
import '../main.dart';
class B {
//This is gonna be the copy of the value
static BrandsCollection brandsCollection;
B(){
brandsCollection.foo();
}
}
我在main中设置了2个静态变量之间的链接:
void main() {
XmlDataReader dataReader = new XmlDataReader();
dataReader.loadContent().then((content) {
GlobalData.brandsCollection = new BrandsCollection(content);
//This is the link
B.brandsCollection = GlobalData.brandsCollection;
runApp(new MyApp());
});
}
当然你必须在B级电话会议之前创建链接。
答案 5 :(得分:0)
class Glob {
//One instance, needs factory
static Glob _instance;
factory Glob() => _instance ??= new Glob._();
Glob._();
//
String account ='johanacct1';
String getServerUrl(){
return 'http://192.168.1.60';
}
String getAccountUrl(){
return getServerUrl()+'/accounts/'+account;
}
}
在另一个文件中使用它:
`
Glob().getAccountUrl(); //http://192.168.1.60/accounts/johanacct1
Glob().account = 'philip.k.dick';
Glob().getAccountUrl(); //http://192.168.1.60/accounts/philip.k.dick
`
当两个文件都在lib /目录中时,它与import 'glob.dart';
一起使用。 (如果在其他情况下有问题,请使用IDK。)
答案 6 :(得分:0)
造成以下代码的原因
[ERROR:flutter / lib / ui / ui_dart_state.cc(148)]未处理的异常:初始化期间读取静态变量'_this @ 69070523'
select
`t1`.*
from
`table_a` as `t1`
inner join `table_2` as `t2` on `t2`.`another_id` = `t1`.`an_id`
where
`t1`.`a_field` = 'foo'
and `t2`.`another_field` = 'bar'
order by
`t1`.`created_at` asc,
`t2`.`another_id` desc;
问题是某种“竞争条件”:在执行// Singleton Pattern
factory KeyValueService() => _this;
static final KeyValueService _this = new KeyValueService._internal();
KeyValueService._internal();
// Exception .. accessing '_this' during initialization
KeyJsonValue _accountAdapter = new KeyJsonValue(_this, accountKey);
时,KeyValueService._internal()
也被初始化,它本身是指尚未初始化的accountAdapter
。
使用函数(=>)代替属性(=)解决了此问题,因为_this
每次调用函数时都会被评估 和并在初始化期间。
new KeyJsonValue(this, …)
答案 7 :(得分:0)
就我而言,问题出在我导入包含静态属性的文件的方式(导入“ package:app / Shared // DIProvider.dart”;)。我不应该加倍/
答案 8 :(得分:0)
我也遇到了这个问题,但是我的原因有点奇怪,所以我想将其发布在这里。 在我的flutter项目中,我在单独的文件中有3个类,比如说main.dart,helper.dart和user.dart。 main和helper都使用静态字段表单用户。但是,即使我在各处都使用了“ import package:...”,问题仍然出在从main和helper读取该字段时,它们的值是不同的。从一个类更改后,从另一类读取时不存在更改。 以我为例,经过数小时的搜索,找到了这种行为的答案之后,我发现在main.dart中,我的导入看起来像这样
import 'package:my_app/user.dart';
在helper.dart中是
import 'package:my_app/User.dart';
将后者更改为小写的“ user.dart”即可解决此问题。
我仍然不知道为什么我的进口商品与众不同(我几乎总是使用自动生成的进口商品),并且还期望飞镖/绒毛进口商品在区分大小写时会区分大小写,我认为这并不奇怪。而且令我更奇怪的是,dart / flutter将这些导入视为单独的文件/库,从而导致了问题。