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

การใช้คําสั่ง tar เพื่อบีบอัดไฟล์ แตกไฟล์ ใน ubuntu

การบีบอัดไฟล์tar เป็นคําสั่งที่ใช้ บีบอัดไฟล์หรือ Directory ให้เป็นไฟล์เดียว เพื่อง่ายต่อการย้ายหรือ copy เราสามารถใช้งานได้ดังนี้

วิธีใช้ PuTTy เชื่อมต่อไปยัง google instance

หลังจากที่เขียนบทความเรื่อง วิธีสร้าง VM Instance ใน google developers console ผมยังไม่ได้อธิบายวิธีการใช้ PuTTy เชื่อมต่อไปยัง google instance ในบทความนี้ผมจะมาอธิบายวิธีเชื่อมต่อ PuTTy ไปยัง google instance อุปกรณ์ที่ต้องใช้มีดังนี้โปรแกรม PuTTy ถ้ายังไม่มีโหลดได้ที่นี่-->Clickโปรแกรม PuTTYgen ถ้ายังไม่มีโหลดได้ที่นี่-->Click

[ภาษาซี] Storage Class

Storage Class คือ สิ่งที่ใช้กําหนดขอบเขตของตัวแปรว่าจะให้ใครสามารถเข้ามาเรียกใช้งานได้บ้าง และยังสามารถกําหนดระยะเวลาว่าจะให้โปรแกรมเก็บค่าของตัวแปรนั้นไว้นานเท่าไรได้ด้วย Storage Class แบ่งออกเป็น 4 ประเภท คือ


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

Build with ❤️ and Astro.

Github profile   Linkedin profile   Instagram   X profile   Youtube channel   Telegram   Email contact   วงแหวนเว็บ