Consumer Flutter Provider, E-Com App 9

When to use Flutter Provider Consumer and why? In this section we will take a quick look at how we can avoid widget-rebuilds.

In our previous section we have seen why we use ChangeNotifierProvider value constructor. However, at the same time, we have used Provider Consumer in our Product Item controller. 

As a result, in the product item controller, we have used Provider.of and Consumer at the same time.

Quite naturally the question pops up. Why did we do that?

Let’s try to understand this topic today, because as we have been building the e-commerce app, it requires making our app more performant.

To make things simpler, let’s take a look at the entry point of the app. 

We have placed Provider on the top.

import 'package:dynamic_color/dynamic_color.dart';
import 'package:e_commerce_app/models/theme.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'models/products.dart';
import 'views/product_detail_screen.dart';
import 'views/products_overview_screen.dart';

final settings = ValueNotifier(
  ThemeSettings(
    sourceColor: const Color.fromARGB(255, 240, 10, 182),
    themeMode: ThemeMode.system,
  ),
);

/// creating a new branch Consumer
///
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => Products(),
          builder: (context, _) => DynamicColorBuilder(
            builder: (lightDynamic, darkDynamic) => ThemeProvider(
              lightDynamic: lightDynamic,
              darkDynamic: darkDynamic,
              settings: settings,
              child: const MyApp(),
            ),
          ),
        ),
      ],
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final theme = ThemeProvider.of(context);
    return MaterialApp(
      title: 'E Commerce App',
      theme: theme.dark(settings.value.sourceColor),
      home: const ProductsOverviewScreen(),
      routes: {
        ProductDetailScreen.routeName: (ctx) => const ProductDetailScreen(),
      },
    );
  }
}

However, to go through all the product objects and show them on the product item page, we have used Change Notifier Provider value constructor. 

And finally we have avoided sending data through the product item class constructor.

That part is okay.

Now, the value property of the Change Notifier Provider expects each product object that we have already instantiated in the Products model. Right?

As a result the child widget Product Item widget will display all the products.

But, we don’t want to rebuild the whole Product Item widget as we press the favorite icon button.

Previously, as we have used the Provider.of, it rebuilds the whole widget.

However, this time, we want more granular widgets to be rebuilt. In short, when we press the Icon button, only the Icon button will rebuild.

Although as the product items there are other properties, such as title, image, etc.

How will we solve this problem?

Consumer Flutter Provider solves the problem

The greatest advantage of Consumer Provider is it helps us to avoid the unnecessary build context misuses. 

For example, in the widget tree, at the bottom we want to rebuild a widget. To do that, we should not use Provider.of at the top so that it will rebuild the whole widget.

Rather we will use the Consumer provider at the nearest possible place of the bottom-most widget.

And if we want to avoid the whole widget-rebuild, we can make the listen property of “Provider.of” false.

We’ve done that exactly.

Let’s see the code.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../models/product.dart';
import '../views/product_detail_screen.dart';

class ProductItem extends StatelessWidget {
  const ProductItem({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final product = Provider.of<Product>(context, listen: false);
    return ClipRRect(
      borderRadius: BorderRadius.circular(10),
      child: GridTile(
        footer: GridTileBar(
          backgroundColor: Theme.of(context).colorScheme.background,

          /// Consumer will only update the Iconbutton
          ///
          leading: Consumer<Product>(
            builder: (ctx, product, child) => IconButton(
              icon: Icon(
                product.isFavorite ? Icons.favorite : Icons.favorite_border,
              ),
              color: Theme.of(context).colorScheme.secondary,
              onPressed: () {
                product.changeStateOfFavorite();
              },
            ),
          ),
          title: Text(
            product.title,
            textAlign: TextAlign.center,
          ),
          trailing: IconButton(
            icon: const Icon(
              Icons.shopping_cart,
            ),
            onPressed: () {},
            color: Theme.of(context).colorScheme.secondary,
          ),
        ),
        child: GestureDetector(
          onTap: () {
            Navigator.of(context).pushNamed(
              ProductDetailScreen.routeName,
              arguments: product.id,
            );
          },
          child: Image.network(
            product.imageUrl,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

Now it not only does make sense, but it enhances the performance of the e-commerce app.

If you want to clone this branch and test it locally please clone the GitHub repository.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

Courses at Educative

GitHub repository

Python and Data Science

Twitter

Comments

3 responses to “Consumer Flutter Provider, E-Com App 9”

  1. […] Finally we will see how it works in the E Commerce app that we’ve been building step-by-step. […]

  2. […] We have seen before, State might be of two types. Local and global.  […]

  3. […] We don’t need to explain again why we have used Provider.of and Consumer at the same time. Because we’ve discussed it before. […]

Leave a Reply