颤动/飞镖静态变量丢失/不断重新初始化

时间:2017-08-19 13:48:05

标签: android ios dart flutter

我正在尝试使用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。

我的应用程序没有在两个操作之间退出或停止。在什么情况下,静态变量会被重新激活?

如果我必须为应用程序保存全局和常用信息,那么除了使用静态变量之外,最好的方法是什么呢?

提前致谢。

9 个答案:

答案 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。 我尝试改变其他用户写的路径,但它仍无法在任何地方工作,所以我使用了这个简单的解决方案:

My Main.dart:

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将这些导入视为单独的文件/库,从而导致了问题。