Cover image

Flutter EP.5 จัดการ State ใน flutter ด้วย Provider

6 Jun 2020

Share to:

สวัสดีครับ ใน EP.4 เราได้เรียนรู้ Project structure file flutter กันไปแล้วนะครับ ในบทความนี้เราจะมาเรียนรู้การจัดการ State ใน Flutter ด้วย Provider กันครับ

โดยปกติเวลาที่เราจะเปลี่ยนข้อมูลใน State เพื่อไป Update UI เราสามารถทําได้ด้วยการใช้คําสั่ง setState() ได้ตามตัวอย่างนี้ (อ่านเพิ่มเติมได้จาก EP.3)

setState((){
   title = "New title";
});

เมื่อมีการ setSate() จะทําให้ Widget นั้น build Widget ใหม่ทั้งหมด ทําให้ประสิทธิภาพของแอปไม่ดีอย่างที่ควรจะเป็น และในความเป็นจริง Application ของเราไม่ได้มีแค่ Widget เดียว และในแต่ละ Widget มีการใช้งาน State ร่วมกัน จึงต้องมี State Management เข้ามาช่วยเพื่อให้เราจัดการ State ได้ง่ายขึ้น

State Management มีอยู่ด้วยกันหลายตัวเช่น Provider, Redux, BLoC/Rx, MobX สําหรับบทความนี้เราจะมาเรียนรู้การจัดการ State ด้วย Provider กันครับ

แนวคิดของการจัดการ State คือจะสร้าง State เก็บไว้ที่เดียว และเมื่อ Widget ไหนต้องการใช้งานก็จะไปหยิบมาใช้ ตัวอย่างตามรูปด้านล่างครับ

Image

การใช้งาน Provider มีดังนี้

Setp1: เพิ่ม Dependencies

เพิ่ม dependencies ของ provider ใน pubspec.yaml

dependencies:
  flutter:
    sdk: flutter

  ...
  provider: ^4.0.0

Step2: สร้าง Model Provider

การสร้าง Model Provider เพื่อเก็บข้อมูลต่างๆที่เราต้องการ และ Method การทํางานต่างๆ รวมไปถึงการ Update Widget เมื่อข้อมูล State เปลี่ยนแปลง ซึ่งการสร้าง Model Provider คือให้เรา สร้าง Class โดย extends class ChangeNotifier และเมื่อต้องการ Update UI เราก็จะเรียก Function notifyListener() ในบทความนี้เราจะยกตัวอย่างสร้างขึ้นมา 2 Model Provider ดังนี้

class CounterProvider extends ChangeNotifier {
  int counter;
  CounterProvider({this.counter = 0});

  increment() {
    counter++;
    notifyListeners();
  }
}

class CounterProvider2 extends ChangeNotifier {
  int counter;
  CounterProvider({this.counter = 0});

  increment(int number) {
    counter += number;
    notifyListeners();
  }
}

Step3: ใช้ Provider ใน Widget

ก่อนอื่น import provider เข้ามาก่อน

import 'package:provider/provider.dart';

เราจะใช้ ChangeNotifierProvider กับ Widget ที่ต้องการจะใช้งาน State ครับ

ในตัวอย่างนี้เราจะใส่ไว้ใน Widget บนสุดเลย ตามนี้ครับ

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.teal,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (_) => CounterProvider(counter: 0)),
          ChangeNotifierProvider(create: (_) => CounterProvider2(counter: 0))
        ],
        child: MyHomePage(title: "My Home")
      ),
    );
  }
}

หรือกรณีที่เราจะใช้งานแค่ 1 Provider ก็สามารถทําแบบนี้ได้ครับ

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.teal,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ChangeNotifierProvider(
        create: (_) => CounterProvider(counter: 0),
        child: MyHomePage(title: "My Home"),
      ),
    );
  }
}

เมื่อเรากําหนด ChangeNotifierProvider แล้ว ใน Widget MyHomePage ของเราจะต้อง get Object ของ Provider ที่เราต้องการโดยใช้คําสั่ง Provider.of() ตามตัวอย่างนี้

...

CounterProvider counterProvider = Provider.of<CounterProvider>(context);
CounterProvider2 counterProvider2 = Provider.of<CounterProvider2>(context);

...

หลังจากนั้นเมื่อเราต้องการจะนําข้อมูล State มาแสดงผลก็สามารถทําได้โดยใช้ Consumer ตามตัวอย่างนี้

...

Consumer<CounterProvider>(
  builder: (context, data, child) => Text(
    '${data.counter}',
    style: Theme.of(context).textTheme.headline4,
  ),
),

...

แต่ในบางครั้งเราต้องการใช้งานหลาย Provider ก็สามารถทําได้ครับโดยใช้ Consumer2, Consumer3, Consumer4, Consumer(N) โดยใช้งานได้สูงสุด 6 Provider ครับ ตามตัวอย่างนี้

...

Consumer2<CounterProvider, CounterProvider2>(
  builder: (context, data, data2, child) => Text(
    '${data.counter} --> ${data2.counter}',
    style: Theme.of(context).textTheme.headline4,
  ),
),

...

กรณีที่ต้องการจะ Update State เราก็ใช้งานผ่าน Object Provider ที่เรา get มาตอนต้นครับตามตัวอย่างนี้

...

floatingActionButton: FloatingActionButton(
  onPressed: () {
    counterProvider.increment();
    counterProvider2.increment(2);
    },
  tooltip: 'Increment',
  child: Icon(Icons.add),
),

...

มาดูตัวอย่างเต็มๆกันครับประมาณนี้

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    CounterProvider counterProvider = Provider.of<CounterProvider>(context);
    CounterProvider2 counterProvider2 = Provider.of<CounterProvider2>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Consumer2<CounterProvider, CounterProvider2>(
              builder: (context, data, data2, child) => Text(
                '${data.counter} --> ${data2.counter}',
                style: Theme.of(context).textTheme.headline4,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          counterProvider.increment();
          counterProvider2.increment(2);
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

การใช้งานก็ประมาณนี้ครับ

แล้วพบกันในบทความหน้านะครับ ขอบคุณครับ

Suggestion blogs

ชอบเล่นควิช หรือเกมส์ทายต่างๆในเฟสบุค ควรอ่าน!

ใครที่ชอบเล่นควิช หรือเกมส์ทายต่างๆในเฟสบุค คุณอาจจะมองว่าเป็นแค่เรื่องเล็กน้อย เล่นสนุกๆ แต่คุณกําลังมีความเสี่ยงที่จะเสียความเป็นส่วนตัวของคุณไป ข้อมูลส่วนตัวของคุณอาจไปตกอยู่ในมือของใครก็ไม่รู้ ที่ผมสนใจก็คือ App พวกนี้มีการร้องขอ Permission(สิทธิ์การเข้าถึงข้อมูล) ของรูปภาพที่คุณอัพโหลดขึ้นไปทั้งหมดบนเฟสบุคของคุณ ผมยํ้าว่าทั้งหมดนะครับ รวมถึงภาพที่เป็น Private และภาพที่คุณถูก Tag ด้วย นั่นหมายความว่าคุณกําลังอนุญาติให้ใครก็ไม่รู้(เจ้าของ App ควิช) มาเข้าถึง หรือ Download รูปส่วนตัวของคุณได้

ESP32 Series รุ่นต่างๆ

สวัสดีครับ บทความนี้เราจะมารู้จักกับ Module ESP32 รุ่นต่างๆว่ามีกี่รุ่น และแต่ละรุ่นมีความแตกต่างกันอย่างไร

วิธีใช้ PL2303 USB to serial TTL

PL2303 USB to serial TTL เป็น อุปกรณ์ที่ใช้แปลงจาก USB เป็น serial TTL ส่วนใหญ่จะนําไปใช้เชื่อมต่อ Computer เข้ากับ Raspberry pi


Copyright © 2019 - 2024 thiti.dev |  v1.19.0 |  Privacy policy |  status | 

            วงแหวนเว็บ