Flutter圈子FlutterFlutter中文社区

flutter之provider使用与简单封装

2020-05-14  本文已影响0人  waiwaaa

Provider是目前Google推荐的状态管理库,国内镜像的地址,现在的最新版本是4.1.1,但是我的sdk版本是1.16,不支持这个最新的,所以改版本用的4.0.0

基本使用

我先是以最简单的主题更改来做基本的更改

第一步,添加Provider依赖,pubspec.yaml

dependencies:
  provider: ^4.0.0

第二步,创建Model

import 'package:flutter/material.dart';

class ThemeModel with ChangeNotifier {
  ThemeData themeData = light();

  bool lighted = true;

  changeTheme() {
    if (lighted) {
      themeData = dark();
    } else {
      themeData = light();
    }
    lighted = !lighted;

    notifyListeners();
  }

  static ThemeData light() {
    return ThemeData(
      textTheme: TextTheme(
          subtitle1: TextStyle(
        color: Colors.black,
        fontSize: 16,
      )),
      backgroundColor: Colors.white,
      brightness: Brightness.light,
      primaryColor: Color(0xff248bfe),
      appBarTheme: AppBarTheme(
        elevation: 0,
        textTheme: TextTheme(
            subtitle1: TextStyle(
          color: Colors.white,
          fontSize: 16,
        )),
      ),
    );
  }

  ThemeData dark() {
    return ThemeData(
      textTheme: TextTheme(
          subtitle1: TextStyle(
        color: Colors.white,
        fontSize: 16,
      )),
      backgroundColor: Colors.black,
      brightness: Brightness.dark,
      primaryColor: Color(0xff000000),
      appBarTheme: AppBarTheme(
        elevation: 0,
        textTheme: TextTheme(
            subtitle1: TextStyle(
          color: Colors.white,
          fontSize: 16,
        )),
      ),
    );
  }
}

一个白天模式一个夜间模式,数据需要混入ChangeNotifier,数据更改后需要调用notifyListeners();来发出通知。

第三步,使用ChangeNotifierProvider

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context1) {
    return ChangeNotifierProvider<ThemeModel>(
      create: (_)=>new ThemeModel(),
      child: //这里必须用Builder,因为Provider.of<ThemeViewModel>(context,listen: true)要拿这里传入的context
        Builder(
          builder: (context)=>      
            MaterialApp(
              debugShowCheckedModeBanner: false,
              title: 'Flutter Demo',
              theme:  Provider.of<ThemeModel>(context,listen: true).themeData,//通过Provider.of取值
              routes: <String,WidgetBuilder>{
                "main/mainpage":(BuildContext context1)=>new MainPage(), //为什么这里可以拿到context1,provider就不行呢???因为该context中并没有Provider
              },
              home: SplashPage(),
            )
        ),
    );

  }
}

第四步,通过点击按钮,获取model并更改模式

InkWell(
          onTap: (){
            Provider.of<ThemeModel>(context,listen:false).changeTheme();
          },
          child: Icon(Icons.cake),
        )

简单的封装

用provider对数据更改来刷新界面时,我们需要有效的控制数据的范围,如果全部放在最上层肯定会影响性能及数据的安全性。所以我们需要对provider写一个通用的组件,方便我们使用。

ProviderWidget封装

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

class ProviderWidget<T extends ChangeNotifier> extends StatefulWidget{
  final T model;
  final Widget Function(BuildContext context, T value, Widget child) builder;
  final Function(T) onReady;

  ProviderWidget({this.model,this.onReady,this.builder});

  @override
  _ProviderWidgetState<T> createState() => _ProviderWidgetState<T>();    
}
    
class _ProviderWidgetState<T extends ChangeNotifier> extends State<ProviderWidget<T>> {
  @override
  void initState() {
    super.initState();
    if(widget.onReady!=null){
      widget.onReady(widget.model);
    }
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<T>(
      create: (_) => widget.model,
      child: Consumer<T>(//因为child
        builder: widget.builder,
      ),
    );
  }
}

使用示例

model类

class TestModel with ChangeNotifier {
  int clickNum=0;

  void add() {
    clickNum++;
    notifyListeners();
  }
}

用widget的地方直接使用

ProviderWidget<TestModel>(
        model:TestModel(), 
        onReady:(model){
          model.toString();
        }, 
        builder:(context, model, child){
          return Column(
            children: <Widget>[
              Text("${model.clickNum}"),
              RaisedButton(child:Text("add"),onPressed: (){
                  model.add();
              })
            ],
          );
        },
      )

本文完整源码请移步github

上一篇下一篇

猜你喜欢

热点阅读