简体   繁体   English

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

[英]Flutter - Persistent State between Pages

I'm trying to store some state during page changes. 我正在尝试在页面更改期间存储一些状态。 So old data values are available when a page is reloaded. 因此,当重新加载页面时,旧的数据值可用。

I've been looking into PageStorage but haven't figured out how it works yet. 我一直在研究PageStorage,但还没有弄清楚它是如何工作的。

I'm writing into the storage with PageStorage.of(context)?.writeState(context, 'Some text is here', identifier: ValueKey('test')); 我正在使用PageStorage.of(context)?.writeState(context, 'Some text is here', identifier: ValueKey('test'));写入存储PageStorage.of(context)?.writeState(context, 'Some text is here', identifier: ValueKey('test')); and then unloading the page with the back button. 然后使用“后退”按钮卸载页面。

When I reload the page (with Navigator.of(context).push() ), using PageStorage.of(context)?.readState(context, identifier: ValueKey('test')); 当我重新加载页面时(使用Navigator.of(context).push() ),使用PageStorage.of(context)?.readState(context, identifier: ValueKey('test')); just gives me null; 只是给我空;

Here's a short sample that I wrote to demonstrate how I'm using it. 这是我写的一个简短示例,以演示如何使用它。 Does anyone know what I'm doing wrong? 有人知道我在做什么错吗?

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

There were multiple issues with the code you provided. 您提供的代码存在多个问题。

The first one being in your MyAppState where you didn't provided a key to your PageStorage . 第一个位于MyAppState ,您没有为PageStorage提供key Indeed without the key , the written data cannot be saved and I quote : 确实,没有密钥,书面数据就无法保存,我引用:

writeState(BuildContext context, dynamic data, {Object identifier}) → void package:flutter writeState(BuildContext上下文,动态数据,{对象标识符})→无效的包:flutter

Write the given data into this page storage bucket using the specified identifier or an identifier computed from the given context. 使用指定的标识符或从给定上下文计算出的标识符将给定数据写入此页面存储桶。 The computed identifier is based on the PageStorageKeys found in the path from context to the PageStorage widget that owns this page storage bucket. 计算的标识符基于从上下文到拥有此页面存储桶的PageStorage小部件的路径中找到的PageStorageKeys。

If an explicit identifier is not provided and no PageStorageKeys are found, then the data is not saved. 如果未提供显式标识符并且未找到PageStorageKeys,则不会保存数据。

To resolve this just create a global variable PageStorageKey mykey = new PageStorageKey("testkey"); 要解决此问题,只需创建一个全局变量PageStorageKey mykey = new PageStorageKey("testkey"); and pass it along the creation of your PageStorage : 并将其传递到创建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,
      ),
    );
  }
}

Then use the same key again to write the data : 然后再次使用相同的键写入数据:

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

Finally the way you update the text is, in my opinion not the best way to do it. 最后,在我看来,更新文本的方法不是最好的方法。 You should create a method (updateText() for example) and call it after you wrote your data. 您应该创建一个方法(例如,updateText())并在写入数据后调用它。

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

As always it's safer to check if the value is non-null to avoid errors. 与往常一样,检查该值是否为非null以避免错误是更安全的。 Here is the full code : 这是完整的代码:

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

With this code, press the button to go to the second page. 使用此代码,按按钮进入第二页。 On the second page press the button to update the text with the data provided in the writeState() method. 在第二页上,按按钮使用writeState()方法中提供的数据更新文本。

Hoping this can help you, 希望这可以帮助您,

Regards 问候

EDIT 编辑

Fist things first, sorry for misunderstanding the point. 首先要拳头,对这一点的误解表示抱歉。

And actually what you want is possible by using Buckets. 实际上,您可以通过使用Bucket实现所需的功能。 Indeed the : PageStorage .of(context).readState(context, identifier: ValueKey(mykey)); 实际上是: PageStorage .of(context).readState(context, identifier: ValueKey(mykey)); can be replace by : 可以替换为:

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

So what you have to do is make your _bucket variable global, then you need to wrap everything you have in your NewPageState within a PageStorage using the same Key and Bucket as your first PageStorage in the MyAppState 因此,您需要做的是使_bucket变量成为全局变量,然后需要使用与NewPageState中的第一个PageStorage相同的Key Bucket ,将PageStorage中的MyAppState PageStorageMyAppState

Doing so you will be able to read using the bucket too and keep your data through navigation. 这样一来,您还可以使用存储桶进行读取,并通过导航保留数据。

Again he is the full code: 同样,他是完整的代码:

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

        ],
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM