一尘不染

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

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'));just给我null;

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

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'));
              });
            },
          )
        ],
      ),
    );
  }
}

阅读 281

收藏
2020-08-13

共1个答案

一尘不染

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

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

writeState(BuildContext上下文,动态数据,{对象标识符})→无效的包:flutter

使用指定的标识符或从给定上下文计算出的标识符将给定数据写入此页面存储桶。计算出的标识符基于从上下文到拥有该页面存储桶的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作为第一个PageStorageMyAppState

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

同样,他是完整的代码:

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();
              });
            },
          )

        ],
      ),
    );
  }
}
2020-08-13