Dart 颤振:子状态小部件的维护状态

Dart 颤振:子状态小部件的维护状态,dart,flutter,flutter-layout,Dart,Flutter,Flutter Layout,我在一个有状态的小部件中有一个listview.builder,并为该项创建了一个单独的有状态小部件(ImageCard)。 在ImageCard小部件中,当我单击它时,我有一个like按钮,它的颜色变为红色(like)、灰色(loke)。 问题是,当我向下滚动并返回时,颜色总是灰色,这意味着没有保存任何状态! 如何通知父有状态小部件保持状态 父有状态小部件 @override Widget build(BuildContext context) { return _buildLis

我在一个有状态的小部件中有一个listview.builder,并为该项创建了一个单独的有状态小部件(ImageCard)。 在ImageCard小部件中,当我单击它时,我有一个like按钮,它的颜色变为红色(like)、灰色(loke)。 问题是,当我向下滚动并返回时,颜色总是灰色,这意味着没有保存任何状态! 如何通知父有状态小部件保持状态

父有状态小部件

@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;
      }
    });
  }
@覆盖
小部件构建(构建上下文){
返回buildListView(模型,scrollController);
}
Widget\u buildListView(
列出型号,滚动控制器(滚动控制器){
返回容器(
子项:ListView.builder(
控制器:滚动控制器,
itemCount:models.length,
itemBuilder:(上下文,int索引){
if(index==models.length-1){
回程旋转三角帆(
颜色:颜色,紫色,
尺寸:30.0,
);
}否则{
返回图像卡(
模型[索引]。regularPhotoUrl,
模型[索引].mediumProfilePhotoUrl,
模型[索引]。名称,
型号[索引]。颜色);
}
}));
}
子状态小部件

@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;
      }
    });
  }
class ImageCard扩展StatefulWidget{
最终字符串imageUrl、userProfilePic、用户名、颜色;
ImageCard(this.imageUrl、this.userProfilePic、this.userName、this.color);
@凌驾
_ImageCardState createState()=>\u ImageCardState();
}
类_ImageCardState扩展状态{
bool isLiked=false,isFollowing=false;
@凌驾
小部件构建(构建上下文){
退还新卡(。。。。
void _onlikedbtclicked(){
设置状态(){
如果(islike)
isLiked=假;
否则{
isLiked=true;
}
});
}

那么你应该单独保存你的状态。你可以制作一个
列表,每个列表项都有一个值。你可能想在某个时候保存或使用数据,那么这个机制就没用了。

flift将自动处理移出屏幕的小部件,当它们被删除时-看起来,它们将被重建,而不是恢复

因此,通常的做法是将状态保存在高级小部件中,该小部件至少包含业务逻辑的一个完整方面,并且不会很快被处理。然后,状态的更改被映射到子小部件中

对于您的特定情况,一个简单的解决方案是:将信息存储在父小部件中,并将其映射到父小部件的构建函数中的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,
      ),
    )
  }
}
类SomeParentState扩展状态{
列出模型;
//.......
@凌驾
小部件构建(构建上下文){
返回buildListView(模型,scrollController);
}
Widget\u buildListView(列表模型,
滚动控制器(滚动控制器){
返回容器(
子项:ListView.builder(
控制器:滚动控制器,
itemCount:models.length,
itemBuilder:(上下文,int索引){
if(index==models.length-1){
回程旋转三角帆(
颜色:颜色,紫色,
尺寸:30.0,
);
}否则{
返回图像卡(
模型[索引]。regularPhotoUrl,
模型[索引].mediumProfilePhotoUrl,
模型[索引]。名称,
型号[索引]。颜色,
模型[索引]。Islike,
模型[索引]。如下所示,
() {
设置状态(){
模型[index].isLiked=!模型[index].isLiked;
});
},
() {
设置状态(){
模型[index].isFollowing=!模型[index].isFollowing;
});
},
);
}
}));
}
}
类ImageCard扩展了无状态小部件{
图像卡(
//...,
我喜欢这个,
这是下面这个,
这个.likeBtnClickedListener,
此.followBtnClickedListener,
)
//...
小部件构建(构建上下文){
回程卡(
//.......
图标按钮(
onPressed:像WebTNClickedListener一样,
),
图标按钮(
onPressed:followBtnClickedListener,
),
)
}
}
这基本上可以解决您的问题。无论如何,用这种方法访问和同步子窗口小部件中的数据更容易


如果您发现保持子小部件处于活动状态更容易,则可以阅读的文档。当小部件移动到看不见的地方时,它将阻止颤振杀死此小部件。但这有导致内存泄漏的风险。

要在
列表视图中保持小部件的状态,您需要或(对于自定义小部件)

这将确保退出屏幕时不会破坏
状态
实例

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

因此,在ImageCard中,您将
isLiked
属性保存在何处?它是否意味着
color
属性?在我的代码中显示,我将其保存在状态中。如果isLiked是真的,请将btn的颜色设置为红色。您是对的!我发现ListView.builder小部件会根据需要创建和销毁项目,并且状态为di物品被销毁时会留下疤痕。因此必须使ImageCard成为无状态Widget感谢您的提示,但@First_Strike解决方案正是我搜索的