颤振-页面之间的持久状态

时间:2018-07-05 15:29:45

标签: flutter

我正在尝试在页面更改期间存储某些状态。因此,在重新加载页面时,可以使用旧的数据值。

我一直在研究PageStorage,但还没有弄清楚它是如何工作的。

我正在使用PageStorage.of(context)?.writeState(context, 'Some text is here', identifier: ValueKey('test'));写入存储,然后使用“后退”按钮卸载页面。

当我重新加载页面(使用Navigator.of(context).push()时,使用PageStorage.of(context)?.readState(context, identifier: ValueKey('test'));只会使我为空;

这是我写的简短示例,以演示如何使用它。有人知道我在做什么错吗?

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  final PageStorageBucket _bucket = new PageStorageBucket();
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: PageStorage(
        child: new MyHomePage(),
        bucket: _bucket,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: FloatingActionButton(
        onPressed: () {
          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
            return new NewPage();
          }));
        },
      ),
    );
  }
}

class NewPage extends StatefulWidget {
  NewPageState createState() => NewPageState();
}

class NewPageState extends State<NewPage> {
  String _text = '';
  @override
  void initState() {
    super.initState();
    _text = PageStorage
        .of(context)
        ?.readState(context, identifier: ValueKey('test'));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[
          Text('The text is $_text'),
          FloatingActionButton(
            onPressed: () {
              setState(() {
                PageStorage.of(context)?.writeState(
                    context, 'Some text is here',
                    identifier: ValueKey('test'));
              });
            },
          )
        ],
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:4)

您提供的代码存在多个问题。

第一个在您的MyAppState中,您没有为key提供PageStorage。确实,没有密钥,书面数据就无法保存,我引用:

  

writeState(BuildContext上下文,动态数据,{对象标识符})→void   包:颤振

     

使用指定的标识符或从给定的上下文计算出的标识符将给定的数据写入此页面存储桶。计算出的标识符基于从上下文到拥有此页面存储桶的PageStorage小部件的路径中找到的PageStorageKeys。

     

如果未提供显式标识符并且未找到 PageStorageKeys,则不会保存数据。

要解决此问题,只需创建一个全局变量PageStorageKey mykey = new PageStorageKey("testkey");并将其传递到创建PageStorage的过程中即可:

 class MyAppState extends State<MyApp> {
  final PageStorageBucket _bucket = new PageStorageBucket();
  @override
  Widget build(context) {
    return new MaterialApp(
      home: PageStorage(
        child: new MyHomePage(),
        bucket: _bucket,
        key: mykey,
      ),
    );
  }
}

然后再次使用相同的键来写入数据:

onPressed: () {
              setState(() {
                PageStorage.of(context).writeState(context, 'Data saved',
                    identifier: ValueKey(mykey));
                updateText();
              });

最后,我认为更新文本的方法不是最好的方法。 您应该创建一个方法(例如,updateText())并在写入数据后调用它。

 updateText() {
    if (PageStorage.of(context) .readState(context, identifier: ValueKey(mykey)) != null) {
      _text = PageStorage .of(context).readState(context, identifier: ValueKey(mykey));
    } 
    else {
      _text = 'PageStorageNull';
    }
  }

和往常一样,检查该值是否为非null以避免错误是更安全的。 这是完整的代码:

void main() => runApp(new MyApp());

PageStorageKey mykey = new PageStorageKey("testkey");

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  final PageStorageBucket _bucket = new PageStorageBucket();
  @override
  Widget build(context) {
    return new MaterialApp(
      home: PageStorage(
        child: new MyHomePage(),
        bucket: _bucket,
        key: mykey,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(context) {
    return Center(
      child: FloatingActionButton(
        onPressed: () {
          Navigator.push(context,
              new MaterialPageRoute(builder: (context) => new NewPage()));
        },
      ),
    );
  }
}

class NewPage extends StatefulWidget {
  NewPageState createState() => NewPageState();
}

class NewPageState extends State<NewPage> {
  String _text;

  @override
  void initState() {
    super.initState();
  }

  updateText() {
    if (PageStorage.of(context) .readState(context, identifier: ValueKey(mykey)) != null) {
      _text = PageStorage .of(context).readState(context, identifier: ValueKey(mykey));
    } 
    else {
      _text = 'PageStorageNull';
    }
  }

  @override
  Widget build(context) {
    return Center(
      child: Column(
        children: <Widget>[
          Text('The text is $_text'),
          FloatingActionButton(
            onPressed: () {
              setState(() {
                PageStorage.of(context).writeState(context, 'Data saved',
                    identifier: ValueKey(mykey));
                updateText();
              });
            },
          )
        ],
      ),
    );
  }
}

使用此代码,按按钮进入第二页。在第二页上,按按钮以使用writeState()方法中提供的数据更新文本。

希望这可以为您提供帮助,

致谢

编辑

首先要拳头,对这一点的误解表示歉意。

实际上,您可以通过使用Bucket实现所需的功能。 实际上,PageStorage .of(context).readState(context, identifier: ValueKey(mykey));可以替换为:

_bucket.readState(context, identifier: ValueKey(mykey));

因此,您需要做的是将_bucket变量设置为全局变量,然后需要使用相同的NewPageStatePageStorage中的所有内容包装到Key Bucket作为PageStorage

中的第一个MyAppState

这样做,您还可以使用存储桶进行读取,并通过导航保留数据。

同样,他是完整代码:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

PageStorageKey mykey = new PageStorageKey("testkey");
final PageStorageBucket _bucket = new PageStorageBucket();

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {

  @override
  Widget build(context) {
    return new MaterialApp(
      home: PageStorage(
        child: new MyHomePage(),
        bucket: _bucket,
        key: mykey,
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(context) {
    return Center(
      child: FloatingActionButton(
        onPressed: () {
          Navigator.push(context,
              new MaterialPageRoute(builder: (context) => new NewPage()));
        },
      ),
    );
  }
}

class NewPage extends StatefulWidget {
  NewPageState createState() => NewPageState();
}

class NewPageState extends State<NewPage> {
  String _text;

  @override
  void initState() {
    super.initState();
    updateText();
  }

  updateText() {

    if (_bucket.readState(context, identifier: ValueKey(mykey)) != null) {
      _text = _bucket.readState(context, identifier: ValueKey(mykey));

    } 
    else {
       print(_bucket.toString());

    }
  }

  @override
  Widget build(context) {
    return PageStorage(
      key:mykey,
      bucket: _bucket,
      child: Column(
        children: <Widget>[
          Text('The text is $_text'),
          FloatingActionButton(
            onPressed: () {
              setState(() {
                _bucket.writeState(context, 'Data saved',
                    identifier: ValueKey(mykey));
                updateText();
              });
            },
          )

        ],
      ),
    );
  }
}