State Management Part 2

Karena framework flutter adalah declarative, untuk mengubah UI, flutter harus me-rebuild ulang.

Untuk itu kita gunakan state management, dimana listener dipasang pada widget yang akan melakukan rebuild ulang. Sementara provider harus dipasang pada parent. Atau istilahnya adalah lifting state up.

Pada main.dart kita pasang provider dengan menggunakan ChangeNotifierProvider, karena widget ProductViewScr() akan melakukan listening dan direbuild jika ada perubahan data.

...
...
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (ctx) => ProductsProvider(),
...
...
//file main.dart

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

import './widgets/product_view_scr.dart';
import './widgets/product_detail_scr.dart';
import './models/products_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (ctx) => ProductsProvider(),
      child: MaterialApp(
        title: 'AZShop',
        theme: ThemeData(
          primarySwatch: Colors.red,
          accentColor: Colors.red[300],
          visualDensity: VisualDensity.adaptivePlatformDensity,
          fontFamily: 'Lato',
        ),
        home: ProductViewScr(),
        routes: {
          ProductDetailScr.routeNm: (ctx) => ProductDetailScr(),
        },
      ),
    );
  }
}

Pada file product_view_scr.dart, untuk mendapatkan data dengan mengakses Provider, yaitu Provider.of(context).productsList; Perhatian, disini kita akan akses products_provider.dart, karena akan mengembalikan list produk.

Tips Provider ini dapat dibayangkan seperti proxy yang memiliki mekanisme untuk memberikan notifikasi jika ada perubahan.

...
...
  Widget build(BuildContext context) {
    final products = Provider.of<ProductsProvider>(context).productsList;
    return GridView.builder(
...
...

Karena pada product_item.dart juga akan melakukan listening terhadap perubahan data, maka pada parent harus ditambahkan Provider.

....
....
 itemBuilder: (ctx, i) => ChangeNotifierProvider(
            create: (ctx) => products[i], child: ProductItem()));

...
...

//file product_view_scr.dart

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

import '../models/products_provider.dart';
import './product_item.dart';

class ProductViewScr extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AZShop'),
      ),
      body: ProductsGrid(),
    );
  }
}

class ProductsGrid extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final products = Provider.of<ProductsProvider>(context).productsList;
    return GridView.builder(
        padding: const EdgeInsets.all(8),
        itemCount: products.length,
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            childAspectRatio: 3 / 2,
            crossAxisSpacing: 8,
            mainAxisSpacing: 8),
        itemBuilder: (ctx, i) => ChangeNotifierProvider(
            create: (ctx) => products[i], child: ProductItem()));
  }
}

Perhatian, pada product_item.dart, yang diakses adalah Provider.of<Product>(context) yaitu file product.dart. Disini product_item.dart akan direbuild jika kita mengubah data isFav. Icon favorite akan disesuaikan sesuai status pada data.

...
...
leading: IconButton(
icon: Icon(
    product.isFav ? Icons.favorite : Icons.favorite_border,
    color: Theme.of(context).accentColor,
),
onPressed: () {
    product.toggleFav();
},
),
...
...
//product_item.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './product_detail_scr.dart';
import '../models/product.dart';

class ProductItem extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final product = Provider.of<Product>(context);
    return ClipRRect(
      borderRadius: BorderRadius.circular(4),
      child: GridTile(
        child: GestureDetector(
          onTap: () {
            Navigator.of(context)
                .pushNamed(ProductDetailScr.routeNm, arguments: product.id);
          },
          child: Image.network(
            product.imgURL,
            fit: BoxFit.cover,
          ),
        ),
        footer: GridTileBar(
          backgroundColor: Colors.black54,
          leading: IconButton(
            icon: Icon(
              product.isFav ? Icons.favorite : Icons.favorite_border,
              color: Theme.of(context).accentColor,
            ),
            onPressed: () {
              product.toggleFav();
            },
          ),
          title: Text(product.title),
          trailing: IconButton(
            icon: Icon(
              Icons.add_shopping_cart,
              color: Theme.of(context).accentColor,
            ),
            onPressed: null,
          ),
        ),
      ),
    );
  }
}
Sharing is caring:

Leave a Comment