Flutter: Maintant state of child stateful widget

flutter setstate() from another class
flutter stateful widget
flutter stateful widget lifecycle
flutter access state from widget
flutter stateful widget constructor
flutter rebuild widget
flutter extend statefulwidget
inherited widget flutter

I have a listview.builder inside a stateful widget and i made a separate stateful widget for the item (ImageCard). inside the ImageCard widget i have a like button when i click it its color change to red(like), gray(dislike). the problem is that when i scroll down and return back the color is always gray which means that no state is saved! how can i notify the parent stateful widget to keep the state?

Parent stateful widget

@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);
              }
            }));
  }

child stateful widget

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

Flutter will automatically disposes the widget that moves out of screen, and when they re-appear, they will be re-built rather than recovered.

So common practice is to save the state in a high-level widget, which contains at least a complete aspect of business logic and is not going to be disposed anytime soon. Then a change in the state is mapped into child widgets.

For your specific case, a simple solution is: you store the information in the parent widget, and maps them to a ImageCard inside the parent widget's build function.

Add isliked,isfollowing property to the model, then

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

This should basically solve your problem. Anyway, it is easier to access and sync the data in the child widgets in this method.

If you find it easier to just keep the child widget alive, you can read the documentation of AutomaticKeepAliveClientMixin. It will stop flutter from killing this widget when it moves out of sight. But it is risky of causing memory leak.

Adding interactivity to your Flutter app, How to implement a stateful widget that responds to taps. When the widget's state changes, the state object calls setState() , telling the a single custom stateful widget that manages a row with two children widgets: an IconButton and Text . have exported the highlight state to the parent while keeping the active state  Flutter Stateful widget - Part2 - How to Access State of Widget. In the previous post explained what is Stateful widget and lifecycle of Stateful widget. This post we are going to learn how to access state of the widget. What is context ? A context is a reference to the location of a Widget within the tree structure of all the Widgets which are

To maintain the state of a widget inside a ListView, you need to AutomaticKeepAlive or AutomaticKeepAliveMixin (for custom widgets)

This will ensure the State instance is not destroyed when leaving the screen

ListView(
  children: [
    // Not kept alive
    Text('Hello World'),
    // kept alive
    AutomaticKeepAlive(
     child: Text("Hello World"),
    ),
  ]
),

StatefulWidget class - widgets library - Dart API, Also by convention, the first argument is key, and the last argument is child , children , or the equivalent. See also: State, where the logic behind a StatefulWidget is  Our learning of flutter starts from here, where we will know about Stateless and Stateful Widgets. First we will get to know about Stateless widget and then we will go to Stateful widget.

You should keep your state separately then. You could make a List<bool> and have one value in there for each of the List items. You probably want to save or use the data at some point anyways, then this mechanism is going to be useless.

Managing Flutter Application State With InheritedWidgets, This article reviews how Flutter's StatefulWidget and InheritedWidget classes can be used InheritedWidgets keep track of their dependents, i.e. the BuildContexts child that has a reference to the State<ModelBinding> — a  02 Flutter: Stateless Widgets. 03 Flutter: Buttons and Stateful widgets. class AwesomeButtonState extends State < AwesomeButton >

Flutter: Experiment to trigger child animation when parent setState, Child widget is StatefulWidget, AnimationController is store in child State: Parent will keep instance of child state and trigger animation every  For example, Checkbox, Slider, InkWell, Form, TextField are stateful widgets. A widget’s state is stored in a State object. When the state changes, the State object calls setState() to tell the framework to redraw the widget. Create stateful widget Example Overview. We will build a Flutter App that has stateful widget named Counter.

State Management in Flutter, On the other hand, Stateful widgets are dynamic and have a state, which In a typical widget tree, when two children of a parent are not in the  Stateful widgets are useful when the part of the user interface you are describing can change dynamically, e.g. due to having an internal clock-driven state, or depending on some system state. For compositions that depend only on the configuration information in the object itself and the BuildContext in which the widget is inflated, consider

Beginning Flutter, Flutter uses widgets to create the user interface (UI), and Dart is the language used The element calls the widget's build method to check for children widgets, and The state object maintains a reference to the widget ( StatefulWidget class)​  Stateful Widget. Some other Widgets will handle some inner data that will change during the Widget’s lifetime. This data hence becomes dynamic. The set of data held by this Widget and which may vary during the lifetime of this Widget is called a State. These Widgets are called Stateful Widgets.

Comments
  • So where within ImageCard are you saving the isLiked property? Is it meant to be the color property?
  • Its shown in my code that i save it in the state class
  • I se the color of the btn to red if isLiked is true
  • your are right!, i figured out that ListView.builder widget creates and destroys items on demand, and the state is discarded when the item is destroyed.so it is a must to make ImageCard a stateless widget
  • thank you for this hint, but @First_Strike solution is exactly what i searching for