Как сбросить состояние виджета Flutter с помощью PageStorageKey? - PullRequest
0 голосов
/ 05 августа 2020

TL; DR: как принудительно инициализировать состояние виджета

У меня есть список вложенных ExpansionTiles с PageStorageKey. У каждой плитки есть атрибут, который можно выбрать / отменить. Выбранные элементы добавляются в список и возвращаются на вызывающую страницу. Эта функция работает хорошо. Проблема в том, что когда я возвращаюсь на страницу выбора, она все еще сохраняет состояние ранее выбранных элементов. После перехода (всплытия) обратно на домашнюю страницу я хотел бы, чтобы все данные состояния, связанные со страницей выбора, были сброшены или удалены и повторно инициализированы.

Я добавил методы deactivate () и dispose (), но они все еще держась за государство. Я также добавил уникальный ключ, но это не помогло.

[домашняя страница ] [1]

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  var txtField = TextEditingController();

  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(
            title: Text('Home Page'),
          ),
          body: Builder(
            builder: (context) => Form(
              child: Container(
                color: Colors.grey[300],
                padding: const EdgeInsets.all(20),
                child: TextFormField(
                  controller: txtField,
                  onTap: () async {
                    final result = await Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (BuildContext context) =>
                            OccupationSelection(),
                      ),
                    );
                    txtField.text = result.toString();
                  },
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    icon: const Icon(Icons.work),
                    labelText: 'Select an Occupation',
                  ),
                ),
              ),
            ),
          ),
        ));
  }
}

class OccupationSelection extends StatelessWidget {
  final List<String> selectedOccupation = List<String>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Select An Occupation'),
      ),
      body: ListView.builder(
        itemCount: occupationDB.length,
        itemBuilder: (BuildContext context, int index) => OccItem(
          context,
          occupationDB[index],
          (String item) {
            selectedOccupation.add(item);
          },
          (String item) {
            selectedOccupation.remove(item);
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Save'),
        onPressed: () {
          Navigator.of(context).pop(selectedOccupation.join('+'));
        },
      ),
    );
  }
}


// Create the Widget for the row
class OccItem extends StatefulWidget {
  final Occupation entry;
  final Function addOccupation;
  final Function delOccupation;
  final context;

  OccItem(this.context, this.entry, this.addOccupation, this.delOccupation);

  @override
  OccItemState createState() => OccItemState();
}

class OccItemState extends State<OccItem> {
  final Color _iconColor = Colors.black;

  Widget _buildTiles(Occupation root) {
    if (root.children.isEmpty) {
      return Container(
        color: Colors.grey[300],
        child: Padding(
          padding: const EdgeInsets.only(
              left: 20.0, top: 10.0, bottom: 20, right: 20),
          child: ListTile(
            //key: _key,
            leading: IconButton(
                icon: Icon(
                    root.occSelected
                        ? Icons.check_box
                        : Icons.check_box_outline_blank,
                    color: _iconColor),
                onPressed: () {
                  root.occSelected == false
                      ? widget.addOccupation('${root.occId}${root.occTitle}')
                      : widget.delOccupation('${root.occId}${root.occTitle}');
                  root.occSelected = !root.occSelected;
                  setState(() {});
                  Scaffold.of(widget.context)
                    ..removeCurrentSnackBar()
                    ..showSnackBar(SnackBar(
                      content: root.occSelected
                          ? Text(
                              'Occupation Selected ${root.occTitle}',
                              style: TextStyle(color: Colors.blueAccent),
                            )
                          : Text(
                              'Occupation Removed ${root.occTitle}',
                              style: TextStyle(color: Colors.redAccent),
                            ),
                      duration: Duration(seconds: 4),
                    ));
                }),
            title: Text(root.occTitle),
          ),
        ),
      ); //Detail item
    }
    return Container(
      color: Colors.grey[300],
      child: Padding(
        padding:
            const EdgeInsets.only(left: 20.0, top: 10.0, bottom: 20, right: 20),
        child: ExpansionTile(
          key: PageStorageKey<Occupation>(root),
          title: Text(root.occTitle),
          children: root.children.map<Widget>(_buildTiles).toList(),
        ),
      ),
    ); //High level item
  }

  void deactivate() {
    super.deactivate();
  }

  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return _buildTiles(widget.entry);
  }
}

class Occupation {
  final String occId;
  final String occTitle;
  bool occSelected;
  List<Occupation> children;

  Occupation(this.occId, this.occTitle, this.occSelected,
      [this.children = const <Occupation>[]]);
}

// Occupation Database
List<Occupation> occupationDB = <Occupation>[
  Occupation(
    '1.',
    'Business',
    false,
    <Occupation>[
      Occupation(
        '1.1.',
        'Management',
        false,
        <Occupation>[
          Occupation('1.1.1.', 'Accounting', false),
          Occupation('1.1.2.', 'Administration', false),
          Occupation('1.1.3.', 'Business Development', false),
          Occupation('1.1.4.', 'Finance | Financial Services | Securities', false),
          Occupation('1.1.5.', 'Human Resources', false),
        ],
      ),
      Occupation(
        '1.2.',
        'Construction | Architecture',
        false,
        <Occupation>[
          Occupation('1.2.1.', 'Commercial', false),
          Occupation('1.2.2.', 'Residential', false),
          Occupation('1.2.3.', 'Design', false),
          Occupation(
            '1.2.4.',
            'Trades',
            false,
            <Occupation>[
              Occupation('1.2.4.1.', 'Brickmason | Blockmason', false),
              Occupation('1.2.4.2.', 'Carpenter', false),
              Occupation('1.2.4.3.', 'Cement Mason | Concrete Finisher', false),
              Occupation('1.2.4.4.', 'Construction', false),
              Occupation('1.2.4.5.', 'Electrician', false),
              Occupation('1.2.4.6.', 'Glazier', false),
              Occupation('1.2.4.7.', 'HVAC', false),
              Occupation('1.2.4.8.', 'Iron', false),
              Occupation('1.2.4.9.', 'Painter', false),
              Occupation('1.2.4.10.', 'Plumber', false),
              Occupation('1.2.4.11.', 'Welder', false),
            ],
          ),
        ],
      ),
    ],
  ), //Business
  Occupation(
    '2.',
    'Education',
    false,
    <Occupation>[
      Occupation('2.1.', 'Administration', false),
      Occupation('2.2.', 'Athletics', false),
      Occupation('2.3.', 'Curriculum Development', false),
      Occupation(
        '2.4.',
        'Teaching',
        false,
        <Occupation>[
          Occupation('2.4.1.', 'Pre-school', false),
          Occupation('2.4.2.', 'Elementary', false),
          Occupation('2.4.3.', 'Middle School', false),
          Occupation('2.4.4.', 'High School', false),
        ],
      ),
    ],
  ), //Education
];

1 Ответ

0 голосов
/ 07 августа 2020

В основном проблема в том, что вы используете глобальную переменную для хранения сведений о профессии. И каждый раз вы используете его напрямую. Либо вы можете создать его копию, когда она будет использоваться, либо вам придется сбросить значения выбора. Это решение основано на сбросе значения occSelected.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  var txtField = TextEditingController();

  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(
            title: Text('Home Page'),
          ),
          body: Builder(
            builder: (context) => Form(
              child: Container(
                color: Colors.grey[300],
                padding: const EdgeInsets.all(20),
                child: TextFormField(
                  controller: txtField,
                  onTap: () async {
                    for (Occupation occupation in occupationDB) {
                      occupation.resetAllValues();
                    }

                    final result = await Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (BuildContext context) =>
                            OccupationSelection(),
                      ),
                    );
                    txtField.text = result.toString();
                  },
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    icon: const Icon(Icons.work),
                    labelText: 'Select an Occupation',
                  ),
                ),
              ),
            ),
          ),
        ));
  }
}

class OccupationSelection extends StatelessWidget {
  final List<String> selectedOccupation = List<String>();

  List<Occupation> occupationList = occupationDB;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Select An Occupation'),
      ),
      body: ListView.builder(
        itemCount: occupationList.length,
        itemBuilder: (BuildContext context, int index) => OccItem(
          context,
          occupationList[index],
          (String item) {
            selectedOccupation.add(item);
          },
          (String item) {
            selectedOccupation.remove(item);
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Text('Save'),
        onPressed: () {
          Navigator.of(context).pop(selectedOccupation.join('+'));
        },
      ),
    );
  }
}

// Create the Widget for the row
class OccItem extends StatefulWidget {
  final Occupation entry;
  final Function addOccupation;
  final Function delOccupation;
  final context;

  OccItem(this.context, this.entry, this.addOccupation, this.delOccupation);

  @override
  OccItemState createState() => OccItemState();
}

class OccItemState extends State<OccItem> {
  final Color _iconColor = Colors.black;

  Widget _buildTiles(Occupation root) {
    if (root.children.isEmpty) {
      return Container(
        color: Colors.grey[300],
        child: Padding(
          padding: const EdgeInsets.only(
              left: 20.0, top: 10.0, bottom: 20, right: 20),
          child: ListTile(
            //key: _key,
            leading: IconButton(
                icon: Icon(
                    root.occSelected
                        ? Icons.check_box
                        : Icons.check_box_outline_blank,
                    color: _iconColor),
                onPressed: () {
                  root.occSelected == false
                      ? widget.addOccupation('${root.occId}${root.occTitle}')
                      : widget.delOccupation('${root.occId}${root.occTitle}');
                  root.occSelected = !root.occSelected;
                  setState(() {});
                  Scaffold.of(widget.context)
                    ..removeCurrentSnackBar()
                    ..showSnackBar(SnackBar(
                      content: root.occSelected
                          ? Text(
                              'Occupation Selected ${root.occTitle}',
                              style: TextStyle(color: Colors.blueAccent),
                            )
                          : Text(
                              'Occupation Removed ${root.occTitle}',
                              style: TextStyle(color: Colors.redAccent),
                            ),
                      duration: Duration(seconds: 4),
                    ));
                }),
            title: Text(root.occTitle),
          ),
        ),
      ); //Detail item
    }
    return Container(
      color: Colors.grey[300],
      child: Padding(
        padding:
            const EdgeInsets.only(left: 20.0, top: 10.0, bottom: 20, right: 20),
        child: ExpansionTile(
          key: PageStorageKey<Occupation>(root),
          title: Text(root.occTitle),
          children: root.children.map<Widget>(_buildTiles).toList(),
        ),
      ),
    ); //High level item
  }

  void deactivate() {
    super.deactivate();
  }

  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return _buildTiles(widget.entry);
  }
}

class Occupation {
  final String occId;
  final String occTitle;
  bool occSelected;
  List<Occupation> children;

  Occupation(this.occId, this.occTitle, this.occSelected,
      [this.children = const <Occupation>[]]);

  resetAllValues() {
    print("This should reset");
    this.occSelected = false;
    for (Occupation child in children) {
      child.resetAllValues();
    }
  }
}

// Occupation Database
List<Occupation> occupationDB = <Occupation>[
  Occupation(
    '1.',
    'Business',
    false,
    <Occupation>[
      Occupation(
        '1.1.',
        'Management',
        false,
        <Occupation>[
          Occupation('1.1.1.', 'Accounting', false),
          Occupation('1.1.2.', 'Administration', false),
          Occupation('1.1.3.', 'Business Development', false),
          Occupation(
              '1.1.4.', 'Finance | Financial Services | Securities', false),
          Occupation('1.1.5.', 'Human Resources', false),
        ],
      ),
      Occupation(
        '1.2.',
        'Construction | Architecture',
        false,
        <Occupation>[
          Occupation('1.2.1.', 'Commercial', false),
          Occupation('1.2.2.', 'Residential', false),
          Occupation('1.2.3.', 'Design', false),
          Occupation(
            '1.2.4.',
            'Trades',
            false,
            <Occupation>[
              Occupation('1.2.4.1.', 'Brickmason | Blockmason', false),
              Occupation('1.2.4.2.', 'Carpenter', false),
              Occupation('1.2.4.3.', 'Cement Mason | Concrete Finisher', false),
              Occupation('1.2.4.4.', 'Construction', false),
              Occupation('1.2.4.5.', 'Electrician', false),
              Occupation('1.2.4.6.', 'Glazier', false),
              Occupation('1.2.4.7.', 'HVAC', false),
              Occupation('1.2.4.8.', 'Iron', false),
              Occupation('1.2.4.9.', 'Painter', false),
              Occupation('1.2.4.10.', 'Plumber', false),
              Occupation('1.2.4.11.', 'Welder', false),
            ],
          ),
        ],
      ),
    ],
  ), //Business
  Occupation(
    '2.',
    'Education',
    false,
    <Occupation>[
      Occupation('2.1.', 'Administration', false),
      Occupation('2.2.', 'Athletics', false),
      Occupation('2.3.', 'Curriculum Development', false),
      Occupation(
        '2.4.',
        'Teaching',
        false,
        <Occupation>[
          Occupation('2.4.1.', 'Pre-school', false),
          Occupation('2.4.2.', 'Elementary', false),
          Occupation('2.4.3.', 'Middle School', false),
          Occupation('2.4.4.', 'High School', false),
        ],
      ),
    ],
  ), //Education
];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...