Flutter UI使用Provide實現主題切換

背景

provide是谷歌官方出品的一個狀態管理框架 flutter-provide,它容許在小部件樹中傳遞數據,它被設計爲ScopedModel的替代品,容許咱們更加靈活地處理數據類型和數據vue

爲何須要狀態管理

在進行項目的開發時,咱們每每須要管理不一樣頁面之間的數據共享,在頁面功能複雜,狀態達到幾十個上百個的時候,咱們會難以清楚的維護咱們的數據狀態,本文將以主題切換這個功能使用狀態管理來說解如何在Flutter中使用provide這個狀態管理框架git

爲何選擇Provide

一開始項目使用的是ScopedModel,使用ScopedModel能夠分離展現邏輯和業務邏輯,並且簡單易用,可是ScopedModel有一些侷限github

  • 若是模型較爲複雜,當狀態更新時,會有較多的沒必要要的更新

使用Providevuex

  • 當狀態發生變化時,widget樹會更新指定的節點,不會進行整顆widget樹的更新
  • Provide有泛型的優點,至關於namespace的特性,使用過vuex的應該知道namespace的重要性,它將咱們的狀態分離開來
  • Provide被設計爲ScopedModel的替代品,一樣也有和ScopedModel的易用性
  • Provide提供了Provide.stream能夠以處理流的方式處理數據,不過目前還存在一些問題

項目地址

flutter-ui, 可參考項目中使用provide方法markdown

效果

如何使用

添加依賴

查看 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 文件async

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通知聽衆刷新ide

封裝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);
    }
}
複製代碼

須要管理多個狀態只須要ui

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
        )
    );
}
複製代碼

最後

歡迎更多學習flutter的小夥伴加入QQ羣 Flutter UI: 798874340

敬請關注咱們正在開發的:efoxTeam/flutter-ui 做者github

相關文章
相關標籤/搜索