Flutter使用Provider进行状态管理的实现

 更新时间:2024年04月01日 11:22:40   作者:风浅月明  
Provider是Flutter中一个非常流行的状态管理工具,它可以帮助开发者更有效地管理Widget树中的数据,本文主要介绍了Flutter使用Provider进行状态管理的实现,感兴趣的可以了解一下

一、使用Provider进行状态管理的基本用法

Provider是Flutter中一个非常流行的状态管理工具,它可以帮助开发者更有效地管理Widget树中的数据。Provider的核心思想是将数据模型放置在Widget树中可以被多个子Widget访问的地方,而不必通过构造函数手动传递。

1.添加provider依赖

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0  

2.创建一个数据模型

import 'package:flutter/material.dart';

class CounterModel with ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners(); // 通知监听者数据改变
  }
}

3.在应用中提供模型

在你的应用中,你需要在一个合适的位置(如MaterialApp的上方)使用ChangeNotifierProvider来创建并提供CounterModel的实例。

import 'package:provider/provider.dart';

void main() {
  runApp(
    // 注意:ChangeNotifierProvider要包装在MaterialApp之外
    ChangeNotifierProvider(
      create: (context) => CounterModel(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

4.使用Consumer或Provider.of读取和显示数据

在你的HomeScreen中,你可以使用ConsumerProvider.of来读取CounterModel的数据,并构建UI。

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Provider Example'),
      ),
      body: Center(
        // 使用Consumer来监听CounterModel
        child: Consumer<CounterModel>(
          builder: (context, counter, child) => Text('${counter.count}'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 不需要监听改变时,可以直接使用Provider.of来访问模型
          Provider.of<CounterModel>(context, listen: false).increment();
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

当你点击浮动按钮时,increment方法会被调用,CounterModel中的计数器会增加,并通过notifyListeners通知Consumer重新构建,这样UI上显示的数字就会更新。

注意:

  • 使用Provider.of(context)时,如果你不需要监听变化,可以设置listen: false,这样可以提高性能。
  • 当模型更新时,只有通过Consumer或者Provider.of(context)(并且listen设置为true)获取模型的Widget才会重新构建。

二、管理多个不同的状态

如果你有多个不同的状态需要管理,你通常会为每种状态创建不同的模型。每个模型专注于管理一组相关的状态数据和行为。这样可以帮助你保持代码的清晰和分离关注点,使得每个模型都保持简单和专注。

但是,如果你的状态数据非常紧密相关,并且它们通常一起改变,那么将它们放在同一个模型中也是有意义的。

1.创建多个模型

计数器模型

class CounterModel with ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

主题色彩模型

class ThemeModel with ChangeNotifier {
  ThemeData _themeData = ThemeData.light();

  ThemeData get themeData => _themeData;

  void toggleTheme() {
    _themeData = _themeData == ThemeData.light() ? ThemeData.dark() : ThemeData.light();
    notifyListeners();
  }
}

2.同时管理多个状态

在你的应用中,你可以使用MultiProvider来同时提供多个模型:

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CounterModel()),
        ChangeNotifierProvider(create: (context) => ThemeModel()),
      ],
      child: MyApp(),
    ),
  );
}

你现在可以根据ThemeModel提供的主题数据来构建你的应用程序:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<ThemeModel>(
      builder: (context, themeModel, child) {
        return MaterialApp(
          theme: themeModel.themeData,
          home: HomeScreen(),
        );
      },
    );
  }
}

这样,你就可以在HomeScreen或者其他任何Widget中分别访问和操作CounterModelThemeModel了。通过这种方式,你可以将应用的不同部分的状态管理分离开来,从而使你的代码更加模块化和可维护。

三、异步获取状态

有时,我们不想在模型内部中直接管理状态,而是每次修改SharedPreferences中的缓存数据,以及直接从SharedPreferences获取状态。更进一步,比如异步从网络获取状态,也是类似的。

比如,我们要管理一个订阅状态。

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

class SubscriptionStatusModel extends ChangeNotifier {

  // 订阅状态的异步读取方法
  Future<bool> get isSubscribed async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getBool('isSubscribeValid') ?? false;
  }

  // 更新SharedPreferences中的订阅状态
  Future<void> updateSubscriptionStatus(bool newStatus) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool('isSubscribeValid', newStatus);
    notifyListeners();  // 通知监听器可能有变化
  }

}

在上面的代码中,isSubscribed 现在是一个异步 getter,每次调用时都会从 SharedPreferences 中读取订阅状态。updateSubscriptionStatus 方法现在会将新状态写入 SharedPreferences 并通知监听器。

这样修改后,你就需要在UI中相应地处理Future。例如,如果你在一个widget中使用这个模型,你可能需要使用 FutureBuilder

FutureBuilder<bool>(
  future: provider.isSubscribed, // 假设` provider `是你的SubscriptionStatusModel实例
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      // 等待数据时返回加载指示器
      return CircularProgressIndicator();
    } else if (snapshot.hasError) {
      // 处理错误情况
      return Text('Error: ${snapshot.error}');
    } else {
      // 使用订阅状态来构建widget
      bool isSubscribed = snapshot.data ?? false;
      return Text(isSubscribed ? 'Subscribed' : 'Not subscribed');
    }
  },
)

实际用例:

Stack(
  alignment: Alignment.center,
  children: [
    CustomScrollView(
       // ...
    ),
    Consumer<SubscriptionStatusModel>(builder: (context, provider, child) {
      return FutureBuilder<bool>(
        future: provider.isSubscribed,  
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            // 等待数据时返回加载指示器
            // return CircularProgressIndicator();
            return SizedBox.shrink();
          } else if (snapshot.hasError) {
            // 处理错误情况
            // return Text('Error: ${snapshot.error}');
            return SizedBox.shrink();
          } else {
            // 使用订阅状态来构建widget
            bool isSubscribed = snapshot.data ?? false;
            return Visibility(
              visible: !isSubscribed,
              child: Positioned(
                left: 0,
                right: 0,
                bottom: 16,
                child: _subscribeButton(),
              ),
            );
          }
        },
      );
    }),
  ],
),

到此这篇关于Flutter使用Provider进行状态管理的实现的文章就介绍到这了,更多相关Flutter Provider状态管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Android 静默安装和智能安装的实现方法

    Android 静默安装和智能安装的实现方法

    静默安装就是无声无息的在后台安装apk,没有任何界面提示。智能安装就是有安装界面,但全部是自动的,不需要用户去点击。下面脚本之家小编给大家介绍下Android 静默安装和智能安装的实现方法,感兴趣的朋友一起看看吧
    2018-01-01
  • Android程序锁的实现以及逻辑

    Android程序锁的实现以及逻辑

    本篇文章主要是介绍Android程序锁的实现以及逻辑,它的目的是可以给程序加锁,上过锁的程序可以解锁,有兴趣的朋友可以了解一下。
    2016-10-10
  • Android中编写简单的手电筒小应用的实例教程

    Android中编写简单的手电筒小应用的实例教程

    这篇文章主要介绍了Android中编写简单的手电筒小应用的实例教程,简单粗暴地控制手机闪光灯的开闭,效果拔群XD 需要的朋友可以参考下
    2016-04-04
  • Android实现圆形菜单悬浮窗

    Android实现圆形菜单悬浮窗

    这篇文章主要为大家详细介绍了Android实现圆形菜单悬浮窗,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Android中ListView下拉刷新的实现方法实例分析

    Android中ListView下拉刷新的实现方法实例分析

    这篇文章主要介绍了Android中ListView下拉刷新的实现方法,涉及Android操作ListView的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • Android 中LayoutInflater.inflate()方法的介绍

    Android 中LayoutInflater.inflate()方法的介绍

    这篇文章主要介绍了Android 中LayoutInflater.inflate()方法的介绍的相关资料,希望通过本文大家能掌握这部分内容,需要的朋友可以参考下
    2017-09-09
  • Flutter实现页面切换后保持原页面状态的3种方法

    Flutter实现页面切换后保持原页面状态的3种方法

    这篇文章主要给大家介绍了关于Flutter实现页面切换后保持原页面状态的3种方法,文中通过示例代码介绍的非常详细,对大家的学习或者使用Flutter具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • Kotlin使用TransitionDrawable实现颜色渐变效果流程讲解

    Kotlin使用TransitionDrawable实现颜色渐变效果流程讲解

    这篇文章主要介绍了Kotlin使用TransitionDrawable实现颜色渐变效果,这里,我们通过TransitionDrawable显示颜色渐变效果,包括背景颜色的变化,以及图片与图片的渐变效果
    2023-02-02
  • Android ViewPager的MVP架构搭建过程

    Android ViewPager的MVP架构搭建过程

    本文主要介绍了ViewPager在Android中的作用以及使用场景,如引导页、图片浏览器、新闻或文章内容的多标签页等,同时,还详细阐述了如何通过MVP架构来搭建ViewPager,将视图和逻辑进行解耦,提高代码的可测试性、可复用性,使代码结构更清晰且易于扩展功能
    2024-10-10
  • Android自定义控件ListView下拉刷新的代码

    Android自定义控件ListView下拉刷新的代码

    今天小编就为大家分享一篇关于Android自定义控件ListView下拉刷新的代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12

最新评论