Флаттер - постоянное состояние между страницами - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь сохранить состояние при изменении страницы. Таким образом, старые значения данных доступны при перезагрузке страницы.

Я изучал 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 голосов
/ 06 июля 2018

Было несколько проблем с кодом, который вы предоставили.

Первый находится в вашем MyAppState, где вы не предоставили key вашему PageStorage. Действительно, без ключа записанные данные не могут быть сохранены, и я цитирую:

writeState (контекст BuildContext, динамические данные, {идентификатор объекта}) → void пакет: флаттер

Запишите данные в эту корзину хранения страниц, используя указанный идентификатор или идентификатор, вычисленный из данного контекста. Вычисляемый идентификатор основан на значениях PageStorageKeys, найденных в пути от контекста к виджету PageStorage, которому принадлежит этот сегмент хранилища страниц.

Если явный идентификатор не указан и не найдены 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().

Надеясь, что это может вам помочь,

Привет

EDIT

Сначала нужно разобраться с вещами, извините за неправильное понимание сути.

А на самом деле то, что вы хотите, возможно с помощью Buckets. Действительно: PageStorage .of(context).readState(context, identifier: ValueKey(mykey)); можно заменить на:

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

Так что вам нужно сделать глобальную переменную _bucket, тогда вам нужно обернуть все, что у вас есть в NewPageState в PageStorage, используя те же 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();
              });
            },
          )

        ],
      ),
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...