Home > Software engineering >  The state of my object is not stored properly
The state of my object is not stored properly

Time:01-13

I want to mark my object as favorite.

I have a list of object <RobotAnimation> which is displayed in a ListView. The class have two fields: title and isFavorite. Marking an object as a favorite works, but there is a problem when it comes to storing that state. When I perform a search of all items, after selecting an item as favorite, my favorite items are not being remembered. It seems like the state is being discarded.

What can I do to fix this problem?

Here's what's going on:

video

Here's my code:

class RobotAnimation {
  String title;
  bool isFavorite;

  RobotAnimation({required this.title, this.isFavorite = false});

  @override
  String toString() {
    return '{Title: $title, isFavortite: $isFavorite}';
  }
}

class Animations extends StatefulWidget {
  const Animations({super.key});

  @override
  State<Animations> createState() => _AnimationsState();
}

class _AnimationsState extends State<Animations> with TickerProviderStateMixin {
  late TabController _tabController;

  List<RobotAnimation> animations = [];
  List<RobotAnimation> favoriteAnimations = [];
  List<String> results = store.state.animations;
  List<String> defaultFavorites = [];

  List<RobotAnimation> getAnimationList(
      List<String> animations, List<String> favorites) {
    List<RobotAnimation> robotAnimations = [];
    for (var animation in animations) {
      bool isFav = false;
      for (var favorite in favorites) {
        if (favorite == animation) {
          isFav = true;
        }
      }
      robotAnimations.add(RobotAnimation(title: animation, isFavorite: isFav));
    }
    return robotAnimations;
  }

  List<RobotAnimation> filterFavorites() {
    List<RobotAnimation> filtered = favoriteAnimations;
    animations.where((element) => element.isFavorite == true).toList();

    return filtered;
  }

  void filterSearchResults(String query) {
    List<RobotAnimation> searchList =
        getAnimationList(results, defaultFavorites);
    log('query: $query');

    List<RobotAnimation> filteredList = searchList
        .where((element) =>
            element.title.toLowerCase().contains(query.toLowerCase()))
        .toList();

    log(searchList.toString());

    log(filteredList.toString());
    setState(() => animations = filteredList);
  }

  @override
  void initState() {
    animations = getAnimationList(results, defaultFavorites);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, _Props>(
      converter: (store) => _mapStateToProps(store),
      builder: (_, props) {
        return Scaffold(
          body: TabBarView(
            ...
            children: [
              Container(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  children: [
                    TextField(
                      onChanged: filterSearchResults,
                      decoration: const InputDecoration(
                        labelText: 'Search',
                        hintText: 'Search animation',
                        prefixIcon: Icon(Icons.search),
                      ),
                    ),
                    Expanded(
                      child: ListView.separated(
                        itemCount: animations.length,
                        separatorBuilder: (context, index) => const Divider(),
                        itemBuilder: (context, index) {
                          return ListTile(
                            onTap: () {
                              props.socket?.animation(IAnimation(
                                  animation: animations[index].title));
                            },
                            title: ExtendedText(
                              animations[index].title,
                              maxLines: 1,
                              overflowWidget: const TextOverflowWidget(
                                position: TextOverflowPosition.middle,
                                align: TextOverflowAlign.center,
                                child: Text(
                                  '...',
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ),
                            ),
                            trailing: Row(
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                IconButton(
                                  onPressed: () {
                                    setState(() {
                                      animations[index].isFavorite
                                          ? animations[index].isFavorite = false
                                          : animations[index].isFavorite = true;
                                    });
                                  },
                                  icon: animations[index].isFavorite
                                      ? Icon(
                                          Icons.favorite,
                                          color: Colors.red.shade500,
                                        )
                                      : Icon(
                                          Icons.favorite_border,
                                          color: Colors.grey.shade500,
                                        ),
                                ),
                              ],
                            ),
                          );
                        },
                      ),
                    )
                  ],
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}

class _Props {
  final Connection? socket;
  final List<String> animations;

  _Props({
    required this.socket,
    required this.animations,
  });
}

_Props _mapStateToProps(Store<AppState> store) {
  return _Props(
    socket: store.state.socket,
    animations: store.state.animations,
  );
}

CodePudding user response:

Try this inside your IconButton onPressed-Method:

setState(() {
  if (animations[index].isFavorite) {
    animations[index].isFavorite = false
    defaultFavorites.remove(animations[index].title)
  } else {
    animations[index].isFavorite = true;
    defaultFavorites.add(animations[index].title)
  }
});

It seems like you always generate a new list of animations based on the two lists List<String>.

  • Related