ReactiveWidgetReactiveValue 用于 Flutter

简单的状态管理 / 响应式状态跟踪,与那些非常复杂的常用 状态管理方法 相比,可以减少样板代码。

用法

pubspec.yaml 中依赖此 GitHub 项目

dependencies:
  flutter:
    sdk: flutter
  flutter_reactive_widget:
    git:
      url: https://github.com/lukehutch/flutter_reactive_widget.git
      ref: main

然后运行 flutter pub get

导入库

import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';

使用 ReactiveValue<T> 声明您的状态(它扩展了 ValueNotifier<T>

final counter = ReactiveValue<int>(0);

然后简单地将任何读取 counter.value 的代码包装在 ReactiveWidget

ReactiveWidget(
  () => Text(
    '${counter.value}',
    style: const TextStyle(fontSize: 20),
  ),
),

ReactiveWidget 中对 counter.value 的简单引用会导致此 ReactiveWidget 开始监听 counter.value 的变化。(如果小部件被处置,此监听器会自动移除。)

任何修改 counter.value 的事件处理程序现在将触发 ReactiveWidget 使用新值进行重建。

持久化的 ReactiveValue 子类

通过使用 PersistentReactiveValue 而不是 ReactiveValue,您还可以跨应用程序重新启动持久化值。

首先在 main 中,您需要初始化 WidgetsFlutterBinding,然后需要调用 await PersistentReactiveValue.init()(它会从后端存储加载任何持久化的值)。

main() async {
  // Both of the following lines are needed, in this order
  WidgetsFlutterBinding.ensureInitialized();
  await PersistentReactiveValue.init();
  
  // Then run the app
  runApp(App());
}

然后您可以使用 PersistentReactiveValue 而不是 ReactiveValue

final counter = PersistentReactiveValue<int>(/* key */ "counter", /* defaultValue */ 0);

如果 counter.value 之前从未设置过,它将被设置为默认值 0,但如果之前在应用程序的某个运行实例中设置过,则会使用键 "counter"SharedPreferences 中恢复之前的值。

每当未来设置 counter.value 时,不仅会更新任何包装的 ReactiveWidget,而且新值还会使用相同的键异步写入到 SharedPreferences 持久化缓存中。

请注意,对于 PersistentReactiveValue<T>T 不能是可空类型(T?),因为空值无法与 SharedPreferences 中不存在的值区分开来。例如,您可能需要为 PersistentReactiveValue<String> 存储空字符串而不是 null。此外,一旦设置了某个值,就没有办法将其取消设置以返回到默认值。

状态存储位置

这篇 Medium 文章 提供了关于如何使用 GetIt 来组织应用程序状态的绝佳建议。将此想法应用于 flutter_reactive_widget

main.dart

main 调用 setUpGetIt()

import 'package:my_app/pages/home_page.dart';
import './service_locator.dart';

main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await PersistentReactiveValue.init();

  // Register state singletons
  setUpGetIt();

  runApp(HomePage());
}

service_locator.dart

使用 GetIt 将所有包含状态的类注册为单例,每页一个状态类(即为页面 home_page.dart 创建 home_page_state.dart

import 'package:my_app/pages/home_page_state.dart';
import 'package:get_it/get_it.dart';

void setUpGetIt() {
  GetIt.instance.registerLazySingleton<HomePageState>(() => HomePageState());
}

pages/home_page_state.dart

定义每个状态类

import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';

/// The persistent state of [HomePage]
class HomePageState {
  final count = PersistentReactiveValue<int>('count', 0);
}

pages/home_page.dart

使用 GetIt.instance<T>() 获取您需要从中读取状态的状态单例类实例

import 'package:my_app/pages/home_page_state.dart';
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

// Get the state of the page
final _homePageState = GetIt.instance<HomePageState>();

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('HomeView'),
        centerTitle: true,
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          ReactiveWidget(
            () => Text(
              '${_homePageState.count.value}',
              style: const TextStyle(fontSize: 20),
            ),
          ),
          IconButton(
            icon: const Icon(Icons.plus_one),
            onPressed: () {
              _homePageState.count.value++;
            },
          ),
        ],
      ),
    );
  }
}

GitHub

查看 Github