Flutter响应式编程插件reactiv的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter响应式编程插件Reactiv的使用

关于Reactiv [响应式编程方法 (reactive/rx)]

Reactiv 是一个轻量级的响应式状态管理工具和依赖注入工具,适用于Flutter的所有平台。它通过响应式变量和依赖注入系统来管理应用程序的状态,确保代码的高效性和可维护性。

picture1.png

功能特点

  • 状态管理:通过响应式变量实现状态管理。
  • 依赖注入:管理单例实例,避免内存泄漏。
  • 轻量级优化API:提供大约150个暴露的方法,编译时检查以防止运行时异常。
  • 跨平台兼容:支持所有平台。

入门指南

要开始在Flutter项目中使用Reactiv,请按照以下步骤操作:

1. 定义控制器和响应式变量
class CounterController extends ReactiveController {
  final count = ReactiveInt(0);

  void increment() {
    count.value++;
  }
}
2. 注入和查找依赖

initState中注入依赖,在build中查找依赖:

/// 注入依赖 => 控制器实例
Dependency.put<CounterController>(CounterController());

/// 查找依赖 => 控制器实例
final controller = Dependency.find<CounterController>();
3. 使用Observer监听响应式变量并更新UI
class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  [@override](/user/override)
  State<CounterScreen> createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  [@override](/user/override)
  void initState() {
    super.initState();
    /// 注入依赖 => 控制器实例
    Dependency.put(CounterController());
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    /// 查找依赖 => 控制器实例
    final controller = Dependency.find<CounterController>();
    return Scaffold(
      appBar: AppBar(
        title: const Text('Reactiv Counter'),
      ),
      body: Center(
        child: Observer(
          listenable: controller.count, // 监听响应式变量
          listener: (count) {
            return Text(
              'Count: $count',
              style: const TextStyle(fontSize: 24),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          controller.increment();
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

状态管理

1. 响应式变量

用户可以通过Reactive<T>类定义响应式变量。例如,定义一个类型为int的响应式变量:

final data = Reactive<int>(0);
可用的响应式类型
用途 响应式类型
String ReactiveString
int ReactiveInt
double ReactiveDouble
num ReactiveNum
bool ReactiveBool
list ReactiveList
set ReactiveSet
泛型响应式类型

对于没有预定义响应式类型的任何数据类型,可以使用Reactive<AnyDataType>。这个泛型类型也适用于自定义类,如数据类等。

2. Observer小部件

在用户界面中,开发者可以使用Observer小部件来监听响应式变量的变化。例如:

Observer(
  listenable: controller.data,
  listener: (data) {
    return Text(
      'Data: $data',
      style: const TextStyle(fontSize: 24),
    );
  },
)

通过设置listenable参数并指定controller.data,开发者可以在响应式变量发生变化时触发listener中的刷新逻辑,从而重建小部件并反映最新的状态。

3. 更新状态

可以通过值设定器更新响应式变量的值。例如:

data.value += 25;

依赖注入

Reactiv 包含一个强大的依赖注入系统,由Dependency类提供支持。

1. put()

使用Dependency.put<T>(T dependency)方法可以轻松地将类的单例实例注入到应用程序中。例如:

Dependency.put<CounterController>(CounterController);

这允许开发人员将类T的单例实例存储并关联到依赖注入系统中。后续获取控制器时不会创建新的实例,而是使用内存中的同一实例,从而实现零内存泄漏。

2. find()

使用Dependency.find<T>()方法可以从内存中检索存储的单例实例。例如:

final controller = Dependency.find<CounterController>();
3. delete()

使用Dependency.delete<T>()方法可以从依赖注册表中删除单例实例。例如:

Dependency.delete<CounterController>();

示例代码

以下是一个完整的示例,展示了如何使用Reactiv进行状态管理和依赖注入:

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: const LaunchPage(),
    );
  }
}

class LaunchPage extends StatelessWidget {
  const LaunchPage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () {
          Navigator.of(context).push(MaterialPageRoute(builder: (context) {
            return const CounterScreen();
          }));
        },
        child: const Text('Next Page'),
      ),
    );
  }
}

class CounterController extends ReactiveController {
  final count = ReactiveInt(0);

  void increment() {
    count.value++;
  }
}

class CounterScreen extends StatefulWidget {
  const CounterScreen({super.key});

  [@override](/user/override)
  State<CounterScreen> createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  [@override](/user/override)
  void initState() {
    super.initState();

    /// 注入依赖 => 控制器实例
    Dependency.put(CounterController());
  }

  final redScaffold = ReactiveBool(false);

  [@override](/user/override)
  Widget build(BuildContext context) {
    /// 查找依赖 => 控制器实例
    final controller = Dependency.find<CounterController>();
    return Observer(
        listenable: redScaffold,
        listener: (isRedScaffold) {
          return Scaffold(
            backgroundColor: isRedScaffold ? Colors.red : null,
            appBar: AppBar(
              title: const Text('Reactiv Counter'),
            ),
            body: Center(
              child: Observer(
                listenable: controller.count, // 监听响应式变量
                listener: (count) {
                  return Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      TextFormField(
                        decoration: InputDecoration(
                          isDense: true,
                          suffix: isRedScaffold ? Icon(Icons.delete) : null,
                        ),
                      ),
                      Text(
                        'Count: $count',
                        style: const TextStyle(fontSize: 24),
                      ),
                    ],
                  );
                },
              ),
            ),
            bottomNavigationBar: ElevatedButton(
                onPressed: () {
                  redScaffold.value = !redScaffold.value;
                },
                child: Text('Change Scaffold')),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                controller.increment();
              },
              child: const Icon(Icons.add),
            ),
          );
        });
  }
}

Reactiv与GetX的比较

使用Reactiv
Controller
class TestPageController extends ReactiveController {
  final count = ReactiveInt(0);

  increment() {
    count.value++;
  }
}
View
class TestPageScreen extends StatelessWidget {
  const TestPageScreen({Key? key}) : super(key: key);

  TestPageController get controller => Dependency.find<TestPageController>();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Observer(
        listenable: controller.count,
        listener: (count) {
          return Center(child: Text('Count: $count'));
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => controller.increment(),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
使用GetX (Rx/Obx)
Controller
class TestPageController extends GetxController {
  final count = RxInt(0);

  increment() {
    count.value++;
  }
}
View
class TestPageScreen extends StatelessWidget {
  const TestPageScreen({Key? key}) : super(key: key);

  TestPageController get controller => Get.find<TestPageController>();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Obx(
        () {
          final count = controller.count.value;
          return Center(child: Text('Count: $count'));
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => controller.increment(),
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

更多关于Flutter响应式编程插件reactiv的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter响应式编程插件reactiv的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,reactive 插件提供了一种简洁的方式来处理响应式编程。虽然 reactive 插件本身并不是 Flutter SDK 的一部分,但通常指的是使用 Flutter 中响应式编程的概念和工具,比如 providerriverpod 或直接使用 Dart 的 rxdart 库来实现响应式状态管理。

为了展示如何在 Flutter 中使用响应式编程,这里我将给出一个使用 providerChangeNotifier 的示例,因为它们是 Flutter 社区中非常流行的响应式编程工具。虽然这不是直接使用 reactive 插件,但它展示了响应式编程的核心概念。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 provider 依赖:

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0  # 确保使用最新版本

2. 创建一个 ChangeNotifier

ChangeNotifier 是 Flutter 提供的一个用于通知监听者的类。当你改变状态时,你可以调用 notifyListeners() 来通知所有监听者。

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

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

3. 使用 MultiProvider 包装你的应用

main.dart 文件中,使用 MultiProvider 来提供 Counter 实例。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter.dart';  // 导入你创建的 Counter 类

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

4. 在 UI 中消费 Counter 实例

在你的 MyHomePage 中,使用 ConsumerSelector 来监听 Counter 的变化。

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

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Consumer<Counter>(
              builder: (context, counter, child) {
                return Text(
                  '${counter.count}',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          final counter = Provider.of<Counter>(context, listen: false);
          counter.increment();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

总结

以上代码展示了如何使用 providerChangeNotifier 在 Flutter 中实现响应式编程。当你点击浮动按钮时,Countercount 属性会增加,并且由于 notifyListeners() 的调用,UI 会自动更新以反映新的计数。

虽然这个示例没有直接使用名为 reactive 的插件,但它展示了 Flutter 中响应式编程的基本概念和实现方法。如果你寻找的是特定名为 reactive 的第三方库,请提供更多细节,以便给出更准确的示例。

回到顶部