1. 程式人生 > 其它 >Flutter中的Provider(一)4.x版本使用

Flutter中的Provider(一)4.x版本使用

技術標籤:flutter

以下為flutter的最基礎使用版本,內容為點選按鍵增加數字

//Provider的基礎用法

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

//資料類
class Model with ChangeNotifier {//必須混入該類
  int _value = 1;

  int get value => _value;

  void increment() {
    _value++;
    notifyListeners();
  }
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Material App Bar'),
        ),
        body: Home(),
      ),
    );
  }
}

class Home extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // Model model = context.watch<Model>();//如果寫在這裡的話外部也需要被Provide包裹
    return Center(
      child: ChangeNotifierProvider<Model>(
        //這裡不能直接使用Provider<Model>,
        // 這個監聽物件會重新整理包含的UI,另外注意要寫泛型
          create: (_) => Model(),
          //1、注意build函式,UI需要包裹在這個build裡面,或者在child屬性裡面使用
          //2、在child屬性裡面使用時候注意獲取不到BuildContext的問題(該問題涉及到BuildContext的原理),針對該問題有以下兩種方式,
          //1)、將UI檢視重新建立新的一個Widget屬性。
          //2)、使用Build進行包裹,如下:
          //  child: Builder(
          //		builder: (context){
          //			return Text('值:${context.watch<Model>().value}');
          //		}
          //	),
          builder: (context, child) {
            Model model = context.watch<Model>();//注意這一句的範圍,需要被Provider包裹
            return Column(
              children: [
              	// 以下三種寫法相同
                Text('計數:${model.value}'), //第一種寫法
                // Text('計數:${context.watch<Model>().value}'), //第二種寫法
                // Text('計數:${Provider.of<Model>(context,listen: true).value}'),//第三種寫法
                // listen預設值為true
                // listen為true時候相當於watch監聽資料
                // listen為false時候相當於read讀取資料
                // read不能在 StatelessWidget.build/State.build 內呼叫.
                // 換句話說, 它可以在除了這兩個方法以外的任意之處呼叫,所以對於賦值的地方都可以使用read。
                // watch則相反
                RaisedButton(
                  onPressed: () {
                  	// 以下三種寫法相同
                    model.increment();  //第一種寫法
                    // context.read<Model>().increment(); //第二種寫法
                    // Provider.of<Model>(context,listen: false).increment();//第三種寫法
                    //這裡不能監聽資料改變,因此不可以使用watch及其類似的函式
                    //如果使用watch則會報錯,錯誤含義大致為嘗試監聽一個來自於永遠不會再次被呼叫的生命週期的provider。
                  },
                  child: Text('增加數'),
                )
              ],
            );
          }),
    );
  }
}