Flutter UI如何使用Provide实现主题切换详解

背景

provide是谷歌官方出品的一个状态管理框架flutter-provide,它允许在小部件树中传递数据,它被设计为ScopedModel的替代品,允许我们更加灵活地处理数据类型和数据

为什么需要状态管理

在进行项目的开发时,我们往往需要管理不同页面之间的数据共享,在页面功能复杂,状态达到几十个上百个的时候,我们会难以清楚的维护我们的数据状态,本文将以主题切换这个功能使用状态管理来讲解如何在Flutter中使用provide这个状态管理框架

为什么选择Provide

一开始项目使用的是ScopedModel,使用ScopedModel可以分离展示逻辑和业务逻辑,而且简单易用,但是ScopedModel有一些局限

如果模型较为复杂,当状态更新时,会有较多的不必要的更新

使用Provide

  • 当状态发生变化时,widget树会更新指定的节点,不会进行整颗widget树的更新
  • Provide有泛型的优势,相当于namespace的特性,使用过vuex的应该知道namespace的重要性,它将我们的状态分离开来
  • Provide被设计为ScopedModel的替代品,同样也有和ScopedModel的易用性
  • Provide提供了Provide.stream可以以处理流的方式处理数据,不过目前还存在一些问题

项目地址

flutter-ui, 可参考项目中使用provide方法

效果

如何使用

添加依赖

查看 pub-install

在pubspec.yaml中引入依赖

dependencies:
 provide: ^1.0.2 #数据管理层

执行

flutter packages get

在需要使用的页面中引入

import 'package:provide/provide.dart'

创建model (这才第一步)

新建 lib/store/models/config_state_model.dart 文件

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart' show ChangeNotifier

class ConfigInfo {
 String theme = 'red';
}
class ConfigModel extends ConfigInfo with ChangeNotifier {
 Future $setTheme(payload) async {
  theme = payload;
  notifyListeners();
 }
}

用法同ScopedModel差不多,不过不需要继承Model类,只需要混入ChangeNotifier,通过notifyListeners通知听众刷新

封装Store (没错,到这里已经要快完成所有步骤了)

新建 lib/store/index.dart 文件

import 'package:flutter/material.dart'
import 'package:provide/provide.dart'
 show
  Providers
  Provider,
  Provide,
  ProviderNode;
import './models/config_state_model.dart' show ConfigModel;

class Store {
 // 我们将会在main.dart中runAPP实例化init
 static init({model, child, dispose = true}) {
  final providers = Providers()
   ..provide(Provider.value(ConfigModel()));
  return ProviderNode(
   child: child,
   providers: providers,
   dispose: dispose
  );
 }

 // 通过Provide小部件获取状态封装
 static connect<T>({builder, child, scope}) {
  return Provide<T>(
   builder: builder,
   child: child,
   scope: scope
  );
 }

 // 通过Provide.value<T>(context)获取封装
 static T value<T>(context, {scope}) {
  return Provide.value<T>(context, scoped: scoped);
 }
}

需要管理多个状态只需要

final providers = Providers()
..provide(Provider.value(ConfigModel()))
..provide(Provider.value(More()));

定义全局的Provide (倒数第二)

lib/main.dart 文件

import 'package:flutter/material.dart';
import 'package:efox_flutter/store/index.dart'
 show Store, ConfigModel;

// 将状态放入到顶层
void main() => runApp(Store.init(child: MainApp()));
class MainApp extends StatefulWidget {
 @override
 MainAppState createState() => MainAppState();
}
class MainAppState extends State<MainApp> {
 @override
 Widget build(BuildContext context) {
  // 获取Provide状态
  return Store.connect<ConfigModel>(
   builder: (context, child, model) {
    return MaterialApp(
     theme: ThemeData(
      primaryColor: Color(model.theme)
     )
    );
   }
  );
 }
}

改变主题状态 (完成)

import 'package:flutter/material.dart';
import 'package:efox_flutter/store/index.dart'
 show ConfigModel, Store;

/**
* name: 颜色名称 如 red
* color:颜色值
* context: 上下文
*/
Widget Edage(name, color, context) {
 return GestrueDetector(
  onTap: () {
   // 修改主题状态
   Store.value<ConfigModel>(context).$setTheme(name)
  }
  child: Container(
   color: Color(color),
   height: 30,
   widtg: 30
  )
 );
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • Flutter自定义实现神奇动效的卡片切换视图的示例代码

    前言 这一段时间,Flutter的势头是越来越猛了,作为一个Android程序猿,我自然也是想要赶紧尝试一把.在学习到动画的这部分后,为了加深对Flutter动画实现的理解,我决定把之前写的一个卡片切换效果的开源小项目,用Flutter"翻译"一遍. 废话不多说,先来看看效果吧: Android iOS Github地址:https://github.com/BakerJQ/Flutter-InfiniteCards 思路 首先,关于卡片的层叠效果,在原Android项目中,是通过Sc

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

    前言: 在Flutter应用中,导航栏切换页面后默认情况下会丢失原页面状态,即每次进入页面时都会重新初始化状态,如果在initState中打印日志,会发现每次进入时都会输出,显然这样增加了额外的开销,并且带来了不好的用户体验. 在正文之前,先看一些常见的App导航,以喜马拉雅FM为例: 它拥有一个固定的底部导航以及首页的顶部导航,可以看到不管是点击底部导航切换页面还是在首页左右侧滑切换页面,之前的页面状态都是始终维持的,下面就具体介绍下如何在flutter中实现类似喜马拉雅的导航效果 第一步:实

  • flutter PageView实现左右滑动切换视图

    本文实例为大家分享了flutter PageView左右滑动切换视图的具体代码,供大家参考,具体内容如下 import 'dart:math'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_x/base/

  • Flutter实现webview与原生组件组合滑动的示例代码

    最近在用Flutter写一个新闻客户端, 新闻详情页中的内容 需要用Flutter的本地Widget和WebView共同展示 . 比如标题/上方的视频播放器是用本地Widget展示, 新闻内容的富文本文字使用webview展示html, 这样就要求标题/视频播放器与webview可以 组合滑动 . ps: 如果把新闻详情页都用html画出, 就不用考虑组合滑动的问题. 找到支持与本地组件共存的webview控件 找一个可以与本地组件共存的webview控件是首要任务, 以下是我测试过的几个库:

  • Flutter pageview切换指示器的实现代码

    PageView 是一个滑动视图列表,它也是继承至 CustomScrollView 的. 在 PageView 里有三个构造函数: PageView - 创建一个可滚动列表. PageView.builder - 创建一个滚动列表,指定数量. PageView.custom - 创建一个可滚动的列表,自定义子项. 效果 代码 // Copyright 2017, the Flutter project authors. Please see the AUTHORS file // for de

  • Flutter UI如何使用Provide实现主题切换详解

    背景 provide是谷歌官方出品的一个状态管理框架flutter-provide,它允许在小部件树中传递数据,它被设计为ScopedModel的替代品,允许我们更加灵活地处理数据类型和数据 为什么需要状态管理 在进行项目的开发时,我们往往需要管理不同页面之间的数据共享,在页面功能复杂,状态达到几十个上百个的时候,我们会难以清楚的维护我们的数据状态,本文将以主题切换这个功能使用状态管理来讲解如何在Flutter中使用provide这个状态管理框架 为什么选择Provide 一开始项目使用的是Sc

  • Flutter的键值存储数据库使用示例详解

    目录 Flutter 键值存储数据库 unqlite unqlite_flutter 快速上手 简单键值对存储 JSON 为什么你应该使用unqlite_flutter? Flutter 键值存储数据库 键值存储是开发中十分常见的需求,在Flutter开发中,一般使用 shared_preferences 插件来实现.shared_preferences 本质上就是将键值对保存到一个XML文件中进行持久化. 而shared_preferences 实际上存在一定缺陷,譬如其性能较差,不适合处理大

  • Flutter 语法进阶抽象类和接口本质区别详解

    目录 1. 接口存在的意义? 2. 继承 VS 实现 3. Dart 中接口与实现的特殊性 4.Dart 中抽象类作为接口的小细节 1. 接口存在的意义? 在 Dart 中 接口 定义并没有对应的关键字.可能有些人觉得 Dart 中弱化了 接口 的概念,其实不然.我们一般对接口的理解是:接口是更高级别的抽象,接口中的方法都是 抽象方法 ,没有方法体.通过接口的定义,我们可以通过定义接口来声明功能,通过实现接口来确保某类拥有这些功能. 不过你有没有仔细想过,为什么接口会存在,引入接口的概念是为了解

  • Vue 2源码阅读 Provide Inject 依赖注入详解

    目录 Provide/Inject 初始化 1. initInjections 依赖初始化 2. initProvide 注入数据初始化 总结 Provide/Inject 初始化 1. initInjections 依赖初始化 该步骤其实发生在 initState 之前,但是由于 provide/inject 一般是配合使用,所以这里调整了一下顺序. 该函数的定义与过程都比较简单: export function initInjections(vm: Component) { const re

  • Flutter Widgets之标签类控件Chip详解

    目录 概述: RawChip Chip InputChip ChoiceChip FilterChip 总结: 概述: Flutter 标签类控件大全ChipFlutter内置了多个标签类控件,但本质上它们都是同一个控件,只不过是属性参数不同而已,在学习的过程中可以将其放在放在一起学习,方便记忆. RawChip Material风格标签控件,此控件是其他标签控件的基类,通常情况下,不会直接创建此控件,而是使用如下控件: Chip InputChip ChoiceChip FilterChip

  • flutter Bloc 更新后事件同步与异步详解

    目录 前言 使用方式 Bloc 新形态用法 事件队列的阻塞属性? 前言 最近,小轰参与了公司 flutter 项目关于 Dart 2.0 的空安全升级工作.我们升级了所有依赖的三方库,其中就包括有 Bloc 库.作为一款使用率颇高的状态管理框架, Bloc 在版本迭代中进行了少许结构和细节的优化,下面是小轰对于 Bloc 新版本的使用总结. 使用方式 小轰使用的 Bloc 版本如下 flutter_bloc: ^7.3.1 通过最简单的例子来学习新知识 创建一个包含 加 减 操作的页面,使用 b

  • Flutter封装组动画混合动画AnimatedGroup示例详解

    目录 一.来源 二.AnimatedGroup使用示例: 三.AnimatedGroup源码 最后 一.来源 项目中遇到混合动画的情况,每次实现都需要生命一堆属性,让代码变得杂乱,难以维护. 参考 iOS 组动画 CAAimationGroup, 随花半天时间封装一个混合动画组件 AnimatedGroup. 此组件基于极简.高扩展.高适用的封装原则,基本满足当前项目开发. 二.AnimatedGroup使用示例: // // AnimatedGroupDemo.dart // flutter_

  • Flutter控制组件显示和隐藏三种方式详解

    目录 方式一:if语句控制 方式二:Offstage组件 方式三: Visibility Offstage和Visibility的区别: 方式一:if语句控制 // 例如: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ if(a=="显示") Text("显示"), Offstage( offstage: false, child: Text("显示"), ),

  • flutter开发技巧自定页面指示器PageIndicator详解

    目录 一.来源 二.效果 三.源码实现 1.flutter_swiper_null_safety 使用示例: 2.PageIndicatorWidget 指示器源码: 三.总结 一.来源 项目中遇到多个需要自定义轮播图指示器的需求,封装成基础组件方便复用: 原理是通过 ValueListenableBuilder 实时监听轮播图的当前索引,然后更新指示器组件,达到最终效果: 二.效果 三.源码实现 1.flutter_swiper_null_safety 使用示例: import 'packag

  • Flutter 弹性布局基石flex算法flexible示例详解

    目录 flex 布局算法 非弹性组件在 main 轴受到的约束是 unbounded fit 参数 Expanded Spacer flex 布局算法 Flutter 弹性布局的基石 是 flex 和 flexible.理解了这两个 widget,后面的row,column 就都轻而易举了.本文用示例的方式详细介绍 flex 的布局算法. 先布局 flex 为 0 或 null 的 child.在 main 轴上 child 受到的约束是 unbounded.如果 crossAxisAlignm

随机推荐