Flutter - removing an item from a list using ListView.builder index and Provider Package

478

From Flutter Official Site

As You have Used the listen: false this will not rebuild the Widget, change this to true will solve the problem

Share:
478
Siddhartha Mishra
Author by

Siddhartha Mishra

Updated on December 28, 2022

Comments

  • Siddhartha Mishra
    Siddhartha Mishra over 1 year

    I am new to flutter and I have a problem removing an item from a list using listview.builder.

    I am making an e-commerce app and I have two pages now: i)'main-product-overview page', ii)'product-favorite page'.

    The problem is in the 'product-favorite page'. So, whenever a user presses the 'favorite iconbutton' in the 'main product-overview page', the selected product is stored in a list in the products class (List _favoriteProducts = []; see code below) and is displayed in the 'product-favorite page'. Now, in the 'product-favorite page', you can unfavorite the product as well, but whenever I try to unfavorite it from the 'product-favorite-page', the product wont be removed or it will be removed in a strange way.

    Here is the code for the favorite screen :

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:shop/providers/products_provider.dart';
    
    class FavoriteScreen extends StatefulWidget {
      static const routeName = '/favorite-screen';
    
      @override
      _FavoriteScreenState createState() => _FavoriteScreenState();
    }
    
    class _FavoriteScreenState extends State<FavoriteScreen> {
      @override
      Widget build(BuildContext context) {
        final products = Provider.of<Products>(context, listen: false);
        products.changeShowFavorites();
        return Scaffold(
          backgroundColor: Colors.white,
          appBar: AppBar(
            toolbarHeight: 80,
            elevation: 0,
          ),
          body: Column(
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  Text(
                    'Your Favorites',
                    style: TextStyle(
                        fontSize: 25,
                        fontWeight: FontWeight.w900,
                        color: Colors.grey.shade800,
                        letterSpacing: 2.5),
                  ),
                  Text(
                    '${products.favorites.length} shoes',
                    style: TextStyle(letterSpacing: 1.3),
                  ),
                ],
              ),
              SizedBox(
                height: 20,
              ),
              Expanded(
                child: ListView.builder(
                  itemBuilder: (ctx, index) => SizedBox(
                    height: 220,
                    child: Container(
                      height: 200,
                      child: Center(
                        child: Row(
                          children: [
                            Image.network(
                              products.favorites[index].imageUrl,
                            ),
                            Expanded(
                              child: Container(
                                height: 80,
                                child: Card(
                                  elevation: 6,
                                  shadowColor: Colors.pink,
                                  child: InkWell(
                                    onTap: () {},
                                    child: ListTile(
                                      title: Text(products.favorites[index].title),
                                      trailing: IconButton(
                                        onPressed: () {
                                          setState(() {
                                            products.removeFromFavorite(
                                                products.items[index].id);
                                          });
                                        },
                                        icon: Icon(
                                          Icons.favorite_outlined,
                                          color: Colors.pink,
                                          size: 30,
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                  itemCount: products.favorites.length,
                ),
              ),
            ],
          ),
        );
      }
    }
    

    here is the code for the products_provider

    import 'package:flutter/material.dart';
    import 'package:flutter/foundation.dart';
    import './product.dart';
    
    class Products with ChangeNotifier {
      List<Product> _items = [
        Product(
          id: 'p1',
          title: 'Nike Air Max 90',
          description:
              'Nothing as fly, nothing as comfortable, nothing as proven. The Nike Air Max 90 stays true to its OG running roots with the iconic Waffle sole, stitched overlays and classic TPU details. Classic colors celebrate your fresh look while Max Air cushioning adds comfort to the journey.',
          price: 120.00,
          imageUrl:
              'https://static.nike.com/a/images/t_PDP_1280_v1/f_auto,q_auto:eco/zwxes8uud05rkuei1mpt/air-max-90-mens-shoe-6n3vKB.jpg',
        ),
        Product(
          id: 'p2',
          title: 'Nike Air Max 95',
          description:
              'The Nike Air Max 95 made its mark as the first shoe to include visible Nike Air cushioning in the forefoot. The Nike Air Max 95 SE Men\'s Shoe energizes the iconic design with updated materials in a variety of textures and accents.',
          price: 135.99,
          imageUrl:
              'https://static.nike.com/a/images/t_PDP_1280_v1/f_auto,q_auto:eco/cjao63pcxo42v6y4sfg7/air-max-95-se-mens-shoe-86pJT7.jpg',
        ),
        Product(
          id: 'p3',
          title: 'Nike Air Max 97',
          description:
              'The Nike Air Max 97 reimagines an iconic running shoe into everyday kicks for kids. With classic water ripple-inspired lines, Max Air cushioning and a durable design, it’s all about bringing a ‘90s fave to a new generation.',
          price: 107.99,
          imageUrl:
              'https://static.nike.com/a/images/t_PDP_1280_v1/f_auto,q_auto:eco/93a42f0a-32ee-4dec-9abe-af669f725b0e/air-max-97-big-kids-shoe-fQk07c.jpg',
        ),
        Product(
          id: 'p4',
          title: 'Nike Air Max 270',
          description:
              'Nike\'s first lifestyle Air Max brings you style, comfort and big attitude in the Nike Air Max 270. The design draws inspiration from Air Max icons, showcasing Nike\'s greatest innovation with its large window and fresh array of colors.',
          price: 140.99,
          imageUrl:
              'https://static.nike.com/a/images/t_PDP_1280_v1/f_auto,q_auto:eco/b089e489-b1e5-4bf0-bc41-cc0168d65b02/air-max-270-react-se-shoe-dr3Pn3.jpg',
        ),
      ];
    
      List<Product> _favoriteProducts = [];
    
      var _showFavorites = false;
    
      List<Product> get items {
        return [
          ..._items
        ]; //[..._items] means we are returning a copy of _items rather than the original items
      }
    
      Product findById(String id) {
        return _items.firstWhere((prod) => prod.id == id);
      }
    
      List<Product> get favorites {
        if (_showFavorites) {
          return _favoriteProducts;
        }
      }
    
      void addFavorites(Product product) {
        if (!_favoriteProducts.contains(product) && product.isFavorite == true) {
          _favoriteProducts.add(product);
        }
        notifyListeners();
      }
    
      void changeShowFavorites() {
        _showFavorites = true;
        notifyListeners();
      }
    
      void removeFromFavorite(String id) {
        Product toRemoveProduct =
            _favoriteProducts.firstWhere((prod) => prod.id == id);
        toRemoveProduct.isFavorite = false;
        _favoriteProducts.remove(toRemoveProduct);
        notifyListeners();
      }
    }
    

    Any help would be appreciated. I am sorry if the question seems chaotic. This is my first time asking on stackoverflow.