Как я могу обеспечить обновление состояния ScopedModelDescendant? - PullRequest
0 голосов
/ 29 марта 2019

Я пишу флаттер приложение с базовыми функциями CRUD. У меня есть экраны для списка элементов, подробного представления элемента и формы редактирования элемента.

Когда я касаюсь подробного экрана элемента из представления списка, данные отображаются правильно после первоначального создания элемента (с использованием отдельной формы).

Когда я нажимаю на форму редактирования на этом подробном экране, данные элемента передаются и предварительно заполняются в форме.

Когда я вносю изменения в данные этого элемента и сохраняю их, я возвращаюсь к подробному виду, но никакие подробности в этом представлении не менялись.

Однако, когда я поднимаюсь по дереву еще на один уровень, элемент в виде списка был обновлен.

Что мне здесь не хватает? Если родительский виджет с scopedModel имеет изменение состояния и уведомляется notifyListener(), разве это не должно течь вниз по дереву виджетов?

Список:

class GiftListDisplayWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<GiftList>(
      builder: (context, child, giftList) => ListView(
        children: giftList.gifts.map((Gift gift) => GiftCard(gift)).toList(),
      )
    );
  }
}

Подробный вид (некоторый код опущен для краткости)

class GiftDetailPage extends StatefulWidget {
  final Gift gift;

  GiftDetailPage(this.gift);

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

class _GiftDetailPageState extends State<GiftDetailPage> {
  Widget get giftProfile {
    return ListView(
      children: [titleSection, textSection, buttonSection, metadataSection],
    );
  }

  Widget get titleSection {...}

  Widget get textSection {...}

  Widget get buttonSection {
    return Container(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          FlatButton(...)
          FlatButton(
            onPressed: () {
              Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => EditGiftFormPage(widget.gift)));
            },
            padding: EdgeInsets.all(10.0),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.edit, color: Colors.indigoAccent),
                Container(
                  margin: const EdgeInsets.only(top: 8.0),
                  child: Text(
                    'EDIT',
                    style: TextStyle(
                      fontSize: 12.0,
                      fontWeight: FontWeight.w400,
                      color: Colors.indigoAccent,
                    ),
                  ),
                ),
              ],
            ),
          ),
          FlatButton(...)
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget get metadataSection {...}

  _launchURL() async {...}

  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<GiftList>(
      builder: (context, child, giftList) => Scaffold(
            appBar: AppBar(
              title: Text('Gift Details'),
            ),
            body: giftProfile,
          ),
    );
  }
}

А на экране редактирования формы:

class EditGiftFormPage extends StatefulWidget {
  final Gift existingGift;

  EditGiftFormPage(this.existingGift);

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

class _EditGiftFormPageState extends State<EditGiftFormPage> {
  TextEditingController nameController = TextEditingController();
  TextEditingController statusController = TextEditingController();
  TextEditingController descriptionController = TextEditingController();

  GiftStatus selectedStatus;

  Gift updatedGift;

  @override
  void initState() {
    nameController.text = widget.existingGift.recipient;
    selectedStatus = widget.existingGift.giftStatus;
    descriptionController.text = widget.existingGift.recipient;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Gift'),
      ),
      body: ScopedModelDescendant<GiftList>(
        builder: (context, child, giftList) => Container(
              color: Colors.white,
              child: Padding(
                padding: const EdgeInsets.symmetric(
                  vertical: 8.0,
                  horizontal: 32.0,
                ),
                child: Column(...),
              ),
            ),
      ),
    );
  }

  save(GiftList giftList) {
    if (nameController.text.isEmpty ||
        descriptionController.text.isEmpty ||
        selectedStatus == null) {
      print('Make sure you have completed the form');
    } else {
      var newGift = Gift(
          id: widget.existingGift.id,
          recipient: nameController.text,
          giftStatus: selectedStatus,
          description: descriptionController.text,
          imageUrl: 'https://picsum.photos/1080/608/?random');
      giftList.update(newGift);
      Navigator.of(context).pop();
    }
  }
}

С учетом того, что я уже написал, я ожидаю, что, поскольку все эти компоненты заботятся о модели giftList, они должны прислушиваться к этой модели, и когда giftList.update вызывается формой, они должны все пересборка.

В настоящее время только представление списка верхнего уровня отображает обновленные данные, состояние не передается через два дочерних виджета.

В моих знаниях явно есть пробел, и если кто-нибудь увидит, что это такое, я бы хотел знать!

...