Flutter: поддержка состояния дочернего виджета с отслеживанием состояния - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть listview.builder внутри виджета с отслеживанием состояния, и я создал отдельный виджет с сохранением состояния для элемента (ImageCard).внутри виджета ImageCard у меня есть кнопка «Мне нравится», когда я щелкаю по ней, ее цвет меняется на красный (нравится), серый (не нравится).проблема в том, что когда я прокручиваю вниз и возвращаюсь назад, цвет всегда серый, что означает, что ни одно состояние не сохраняется!Как я могу уведомить родительский виджет с сохранением состояния?

Родительский виджет с контролем состояния

@override
  Widget build(BuildContext context) {
    return _buildListView(models, _scrollController);
  }

  Widget _buildListView(
      List<PhotoModel> models, ScrollController scrollController) {
    return Container(
        child: ListView.builder(
            controller: scrollController,
            itemCount: models.length,
            itemBuilder: (context, int index) {
              if (index == models.length - 1) {
                return SpinKitThreeBounce(
                  color: Colors.purple,
                  size: 30.0,
                );
              } else {
                return ImageCard(
                    models[index].regularPhotoUrl,
                    models[index].mediumProfilePhotoUrl,
                    models[index].name,
                    models[index].color);
              }
            }));
  }

дочерний виджет с контролем состояния

class ImageCard extends StatefulWidget {
  final String imageUrl, userProfilePic, userName, color;

  ImageCard(this.imageUrl, this.userProfilePic, this.userName, this.color);

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

class _ImageCardState extends State<ImageCard> {
  bool isLiked = false, isFollowing = false;

  @override
  Widget build(BuildContext context) {
    return new Card( ....

void _onLikedBtnClicked() {
    setState(() {
      if (isLiked)
        isLiked = false;
      else {
        isLiked = true;
      }
    });
  }

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

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

Таким образом, обычной практикой является сохранение состояния в высокомвиджет уровня, который содержит, по крайней мере, полный аспект бизнес-логики и не собирается утилизироваться в ближайшее время.Затем изменение состояния отображается на дочерние виджеты.

Для вашего конкретного случая простое решение: вы сохраняете информацию в родительском виджете и сопоставляете ее с картой ImageCard внутри функции сборки родительского виджета.

Добавьте к модели свойство isliked, isfollowing, затем

class SomeParentState extends State<SomeParent> {
  List<Model> models;

  //.......

  @override
  Widget build(BuildContext context) {
    return _buildListView(models, _scrollController);
  }

  Widget _buildListView(List<PhotoModel> models,
      ScrollController scrollController) {
    return Container(
        child: ListView.builder(
            controller: scrollController,
            itemCount: models.length,
            itemBuilder: (context, int index) {
              if (index == models.length - 1) {
                return SpinKitThreeBounce(
                  color: Colors.purple,
                  size: 30.0,
                );
              } else {
                return ImageCard(
                  models[index].regularPhotoUrl,
                  models[index].mediumProfilePhotoUrl,
                  models[index].name,
                  models[index].color,
                  models[index].isLiked,
                  models[index].isFollowing,
                      () {
                    setState(() {
                      models[index].isLiked = !models[index].isLiked;
                    });
                  },
                      () {
                    setState(() {
                      models[index].isFollowing = !models[index].isFollowing;
                    });
                  },
                );
              }
            }));
  }
}


class ImageCard extends StatelessWidget{

  ImageCard(
      //...,
      this.isLiked,
      this.isFollowing,
      this.likeBtnClickedListener,
      this.followBtnClickedListener,
      )
  //...
  Widget build(BuildContext context){
    return Card(
      //.......
      IconButton(
        onPressed: likeBtnClickedListener,
      ),
      IconButton(
        onPressed: followBtnClickedListener,
      ),
    )
  }
}

Это должно решить вашу проблему.В любом случае, в этом методе проще получить доступ и синхронизировать данные в дочерних виджетах.

Если вам проще поддерживать живой дочерний виджет, вы можете прочитать документацию AutomaticKeepAliveClientMixin .Он остановит трепет от убийства этого виджета, когда он исчезнет из поля зрения.Но это может привести к утечке памяти.

0 голосов
/ 23 ноября 2018

Чтобы поддерживать состояние виджета внутри ListView, вам необходимо AutomaticKeepAlive или AutomaticKeepAliveMixin (для пользовательских виджетов)

Это обеспечит State Экземпляр не уничтожается при выходе из экрана

ListView(
  children: [
    // Not kept alive
    Text('Hello World'),
    // kept alive
    AutomaticKeepAlive(
     child: Text("Hello World"),
    ),
  ]
),
0 голосов
/ 23 ноября 2018

Тогда вы должны хранить свое состояние отдельно.Вы можете сделать List<bool> и иметь одно значение для каждого элемента списка.Возможно, вы все равно захотите сохранить или использовать данные в какой-то момент, тогда этот механизм окажется бесполезным.

...