Flutter状态管理插件state_property的使用

Flutter状态管理插件state_property的使用

简介

state_property 是一个库,它实现了状态属性模式来根据系统当前的状态解析其行为。在 Flutter 中的一个现有例子是 Material State Property,它用于根据按钮的不同状态(如悬停、按下或聚焦)来解析其样式。

例如,在 Flutter 中,一个 TextButton 可以根据是否处于悬停、按下或聚焦等状态来解析其样式:

TextButton(
    onPressed: () {},
    child: const Text('TextButton'),
    style: ButtonStyle(
        foregroundColor: MaterialStateProperty.resolveWith((states) {
            if (states.contains(MaterialState.pressed) || states.contains(MaterialState.hovered)) {
                return Colors.blue;
            }
            return Colors.grey;
        }),
    )
);

使用 1: 通用加载状态

假设我们有一个系统可以处于三种状态:pending(等待)、success(成功)和 fail(失败)。这些状态可以描述任何可以执行任务并可能成功或失败的系统,比如网络上的API调用或文件系统的数据读取。我们可以使用状态属性来定义每个状态的行为,如下所示:

import 'package:state_property/state_property.dart';

enum LoadingStates {
  loading,
  success,
  fail,
}

abstract class LoadingStateProperty<ResolverType>
    implements StateProperty<LoadingStates, ResolverType> {
  [@override](/user/override)
  ResolverType? resolve(Set<LoadingStates> states);

  static StateProperty<LoadingStates, ResolverType> loading<ResolverType>(
        StatelessResolver<ResolverType> resolver) =>
    StateProperty.resolveState<LoadingStates, ResolverType>(
      resolver,
      LoadingStates.loading,
    );

  static StateProperty<LoadingStates, ResolverType> success<ResolverType>(
        StatelessResolver<ResolverType> resolver) =>
     StateProperty.resolveState<LoadingStates, ResolverType>(
      resolver,
      LoadingStates.success,
    );

  static StateProperty<LoadingStates, ResolverType> fail<ResolverType>(
        StatelessResolver<ResolverType> resolver) =>
     StateProperty.resolveState<LoadingStates, ResolverType>(
      resolver,
      LoadingStates.fail,
    );

  static StateProperty<LoadingStates, ResolverType> resolveWith<ResolverType>(
        StatefulResolver<LoadingStates, ResolverType> resolver) =>
    StateProperty.resolveWith<LoadingStates, ResolverType>(
      resolver,
    );

  static StateProperty<LoadingStates, ResolverType> all<ResolverType>(
        StatelessResolver<ResolverType> resolver) =>
    StateProperty.all<LoadingStates, ResolverType>(
      resolver,
    );

  static StateProperty<LoadingStates, Null> never<ResolverType>(
        StatelessResolver<ResolverType> resolver) =>
    StateProperty.never();
}

我们的 LoadingStateProperty 类实现了由库提供的 StateProperty 接口,以定义一个可以处于上述三种加载状态之一的系统。它重用了库中的四个核心状态属性来构建其加载状态属性:

1. resolveWith - 最灵活的状态属性

该属性允许根据提供的状态集动态解析行为。

final isLoadingStateProperty = LoadingStateProperty.resolveWith<bool>((states) {
  return states.contains(LoadingStates.loading);
});

isLoadingStateProperty.resolve({LoadingStates.loading}); // true
isLoadingStateProperty.resolve({LoadingStates.success}); // false

2. resolveState - 在给定状态下解析行为,否则为 null

final successStateProperty = LoadingStateProperty.resolveWith<bool>(() {
  return true;
}, LoadingStates.success);

successStateProperty.resolve({LoadingStates.success}); // true
successStateProperty.resolve({LoadingStates.loading}); // false

3. all - 无论系统的当前状态如何,解析给定行为

final trueStateProperty = LoadingStateProperty.all<bool>(() {
  return true;
});

trueStateProperty.resolve({LoadingStates.done}); // true
trueStateProperty.resolve({LoadingStates.loading}); // true

4. never - 不论系统的当前状态如何,解析为 null

final nullStateProperty = LoadingStateProperty.all<bool>(() {
  return true;
});

nullStateProperty.resolve({LoadingStates.done}); // null
nullStateProperty.resolve({LoadingStates.loading}); // null

使用 2: 在小部件中使用加载状态

现在我们已经构建了一个描述加载状态的状态属性,我们可以将其应用到一个支持基于当前加载状态的不同构建器的 Flutter 小部件中。

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

class Loader extends StatefulWidget {
  final Future<void> Function() load;
  LoadingStateProperty<Widget> builder;

  Loader({
    required this.load,
    required this.builder,
  });

  [@override](/user/override)
  _LoaderState createState() => _LoaderState();
}

class _LoaderState extends State<Loader> {
  LoadingState _state;

  [@override](/user/override)
  void initState() {
    super.initState();

    // 当小部件首次构建时开始加载数据。
    _state = LoadingStates.loading;
    widget.load().then((_resp) {
      setState(() {
        _state = LoadingStates.success;
      });
    }).catchError((e) {
      setState(() {
        _state = LoadingStates.fail;
      });
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return widget.builder.resolve(_state) ?? SizedBox();
  }
}

// 一个具有不同加载行为的小部件。
class MyLoadingWidget extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Loader(
      builder: LoadingStateProperty.resolveWith<Widget>((states) {
        if (states.contains(LoadingStates.success)) {
          return Text('Done!');
        }

        if (states.contains(LoadingStates.fail)) {
          return Text('Something went wrong');
        }

        return const CircularProgressIndicator();
      }),
    );
  }
}

// 一个只有在加载成功后才显示UI的小部件。
class SuccessfulLoadingWidget extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Loader(
      builder: LoadingStateProperty.resolveState<Widget>(() => Text('Done!'), LoadingStates.success),
    );
  }
}

更多关于Flutter状态管理插件state_property的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件state_property的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


state_property 是一个非常轻量级的 Flutter 状态管理插件,适用于小型项目或简单的状态管理需求。它通过在 StatefulWidget 中使用一个 StateProperty 对象来管理状态,从而简化状态管理的过程。

安装

首先,你需要在 pubspec.yaml 文件中添加 state_property 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  state_property: ^1.0.0

然后运行 flutter pub get 来安装依赖。

基本用法

  1. 创建一个 StateProperty 对象

    你可以通过继承 StateProperty 类来创建一个自定义的状态属性类,或者直接使用 StateProperty 的默认实现。

    import 'package:state_property/state_property.dart';
    
    class CounterState extends StateProperty<int> {
      CounterState() : super(0);
    
      void increment() {
        value++;
        notifyListeners();
      }
    }
    
  2. StatefulWidget 中使用 StateProperty

    你可以将 StateProperty 对象作为 StatefulWidget 的状态来使用。

    import 'package:flutter/material.dart';
    import 'package:state_property/state_property.dart';
    
    class CounterApp extends StatefulWidget {
      @override
      _CounterAppState createState() => _CounterAppState();
    }
    
    class _CounterAppState extends State<CounterApp> {
      final CounterState _counterState = CounterState();
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: Text('StateProperty Example')),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('You have clicked the button this many times:'),
                  StateBuilder(
                    state: _counterState,
                    builder: (BuildContext context, int value) {
                      return Text(
                        '$value',
                        style: Theme.of(context).textTheme.headline4,
                      );
                    },
                  ),
                ],
              ),
            ),
            floatingActionButton: FloatingActionButton(
              onPressed: _counterState.increment,
              child: Icon(Icons.add),
            ),
          ),
        );
      }
    }
    
  3. 使用 StateBuilder 监听状态变化

    StateBuilderstate_property 提供的一个小部件,用于监听 StateProperty 的状态变化,并在状态变化时重新构建 UI。

    StateBuilder(
      state: _counterState,
      builder: (BuildContext context, int value) {
        return Text(
          '$value',
          style: Theme.of(context).textTheme.headline4,
        );
      },
    );
回到顶部