Bloc Pattern을 단순한 구조로 만들어주는 Provider Pattern.

 

 

1. CountProvider.dart

import "package:flutter/material.dart";

class CountProvider extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void plus() {
    _count++;
    notifyListeners();
  }

  void minus() {
    _count--;
    notifyListeners();
  }
}

import "package:flutter/foundation.dart";

class CountProvider with ChangeNotifier, DiagnosticableTreeMixin {
  int _count = 0;
  int get count => _count;

  void plus() {
    _count++;
    notifyListeners();
  }

  void minus() {
    _count--;
    notifyListeners();
  }

  /// Makes `Counter` readable inside the devtools by listing all of its properties
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('count', count));
  }
}

 

2. main.dart

import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
import "package:provider_example/home.dart";

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Provider Sample",
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity
      ),
      // home: ChangeNotifierProvider(
      //   create: (BuildContext context) => CountProvider(),
      //   child: const Home(title: "Provider example"),
      // ),

      home: MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (BuildContext context) => CountProvider()),
        ],
        child: const Home(title: "Provider example"),
      ),
    );
  }
}

 

3. home.dart

import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
import "package:provider_example/CountView.dart";

class Home extends StatelessWidget {
  final String title;

  const Home({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    print("Widget : Home");

    // listen: false는 현재 Widget은 Rendering하지 않도록 한다. But 하위 Widget은 여전히 다시 Rendering된다.
    // 하위 Widget에서도 Rendering을 방지할려면 하위 Widget에서 Consumer를 사용하면 된다.
    CountProvider countProvider =
        Provider.of<CountProvider>(context, listen: false);

    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: const CountView(),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          IconButton(
              onPressed: () => countProvider.plus(),
              icon: const Icon(Icons.add)),
          IconButton(
              onPressed: () => countProvider.minus(),
              icon: const Icon(Icons.remove))
        ],
      ),
    );
  }
}
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";
import "package:provider_example/CountView.dart";

class Home extends StatelessWidget {
  final String title;

  const Home({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    print("Widget : Home");

    // listen: false는 현재 Widget은 Rendering하지 않도록 한다. But 하위 Widget은 여전히 다시 Rendering된다.
    // 하위 Widget에서도 Rendering을 방지할려면 하위 Widget에서 Consumer를 사용하면 된다.
    // CountProvider countProvider =
    //     Provider.of<CountProvider>(context, listen: false);

    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: const CountView(),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          IconButton(
              //onPressed: () => countProvider.plus(),

              /// Calls `context.read` instead of `context.watch` so that it does not rebuild
              /// when [CountProvider] changes.
              onPressed: () => context.read<CountProvider>().plus(),
              icon: const Icon(Icons.add)),
          IconButton(
              //onPressed: () => countProvider.minus(),

              /// Calls `context.read` instead of `context.watch` so that it does not rebuild
              /// when [CountProvider] changes.
              onPressed: () => context.read<CountProvider>().minus(),
              icon: const Icon(Icons.remove))
        ],
      ),
    );
  }
}

 

4. CountView.dart

import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";

class CountView extends StatelessWidget {
  const CountView({super.key});

  @override
  Widget build(BuildContext context) {
    print("Widget : CountView");

    return Center(
      // 현재 Widget을 반복하여 Rendering한다.
      // child: Text(
      //   Provider.of<CountProvider>(context).count.toString(),
      //   style: const TextStyle(fontSize: 80),
      // ),

      // 현재 Widget을 반복하여 Rendering하지 않는다.
      child: Consumer<CountProvider>(builder: (context, provider, child) {
        return Text(
          provider.count.toString(),
          style: const TextStyle(fontSize: 80),
        );
      }),
    );
  }
}
import "package:flutter/material.dart";
import "package:provider/provider.dart";
import "package:provider_example/CountProvider.dart";

class CountView extends StatelessWidget {
  const CountView({super.key});

  @override
  Widget build(BuildContext context) {
    print("Widget : CountView");

    return Center(
      // 현재 Widget을 반복하여 Rendering한다.
      // child: Text(
      //   Provider.of<CountProvider>(context).count.toString(),
      //   style: const TextStyle(fontSize: 80),
      // ),

      // 현재 Widget을 반복하여 Rendering하지 않는다.
      // child: Consumer<CountProvider>(builder: (context, provider, child) {
      //   return Text(
      //     provider.count.toString(),
      //     style: const TextStyle(fontSize: 80),
      //   );
      // }),

      /// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
      child: Text(
        context.watch<CountProvider>().count.toString(),
        style: const TextStyle(fontSize: 80),
      ),
    );
  }
}