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

问题描述 投票:1回答:1

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

我一直在研究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'));只给我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'));
              });
            },
          )
        ],
      ),
    );
  }
}
flutter
1个回答
3
投票

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

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

writeState(BuildContext context,dynamic data,{Object identifier})→void package: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';
    }
  }

一如既往,检查值是否为非空以避免错误更安全。这是完整的代码:

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()方法中提供的数据更新文本。

希望这可以帮助你,

问候

编辑

首先,对不起误解这一点。

实际上你可以通过使用Buckets来实现。确实: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();
              });
            },
          )

        ],
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.