flutter 响应式观察值并更新UI

响应式编程是一种以对数据随时间变化做出反应为中心的范式。它有助于自动传播更新,从而可确保 UI 和数据保持同步。用 Flutter 术语来说,这意味着只要状态发生变化就会自动触发重建。

Observables

Observables是响应式编程的核心。这些数据源会在数据发生变化时向订阅者发出更新。Dart 的核心可观察类型是 Stream。

当状态发生变化时,可观察对象会通知侦听器。从用户交互到数据获取操作的任何事情都可以触发此操作。这有助于 Flutter 应用程序实时响应用户输入和其他更改。

Flutter 有两种类型:ValueNotifierChangeNotifier,它们是类似 observable 的类型,但不提供任何真正的可组合性计算。

ValueNotifier

Flutter 中的类ValueNotifier在某种意义上是响应式的,因为当值发生变化时它会通知观察者,但您需要手动监听所有值的变化来计算完整的值。

1、监听

ini 复制代码
  // 初始化
 final ValueNotifier<String> fristName = ValueNotifier('Tom');
 final ValueNotifier<String> secondName = ValueNotifier('Joy');
 late final ValueNotifier<String> fullName;

  @override
  void initState() {
    super.initState();
    fullName = ValueNotifier('${fristName.value} ${secondName.value}');

    fristName.addListener(_updateFullName);
    secondName.addListener(_updateFullName);
  }
  
  void _updateFullName() {
    fullName.value = '${fristName.value} ${secondName.value}';
  }


  //更改值得时候
  firstName.value = 'Jane'
  secondName.value = 'Jane'

2、使用ValueListenableBuilder更新UI

less 复制代码
 //通知观察者
 ValueListenableBuilder<String>(
   valueListenable: fullName,
   builder: (context, value, child) => Text(
      '${fristName.value} ${secondName.value}',
       style: Theme.of(context).textTheme.headlineMedium,
   ),
),

ChangeNotifier

1、监听

ini 复制代码
  String _firstName = 'Jane';
  String _secondName = 'Doe';

  String get firstName => _firstName;
  String get secondName => _secondName;
  String get fullName => '$_firstName $_secondName';

  set firstName(String newName) {
    if (newName != _firstName) {
      _firstName = newName;
      // Triggers rebuild
      notifyListeners();
    }
  }

  set secondName(String newSecondName) {
    if (newSecondName != _secondName) {
      _secondName = newSecondName;
      // Triggers rebuild
      notifyListeners();
    }
  }
  
  //更改值得时候
  firstName.value = 'Jane'
  secondName.value = 'Jane'

2、使用AnimatedBuilder更新UI

less 复制代码
//通知观察者
AnimatedBuilder(
     animation: fullName,
     builder: (context, child) => Text(
     fullName,
     style: Theme.of(context).textTheme.headlineMedium,
    ),
 ),

get

GetX将响应式编程变得非常简单。

  • 您不需要创建 StreamController。
  • 您不需要为每个变量创建一个 StreamBuilder。
  • 你不需要为每个状态创建一个类。
  • 你不需要创造一个终极价值。

使用 Get 的响应式编程就像使用 setState 一样简单。 让我们想象一下,您有一个名称变量,并且希望每次更改它时,所有使用它的小组件都会自动刷新。

1、监听以及更新UI

ini 复制代码
//这是一个普通的字符串
var name = 'Jonatas Borges';
为了使观察变得更加可观察,你只需要在它的附加上添加".obs"。
var name = 'Jonatas Borges'.obs;
而在UI中,当你想显示该值并在值变化时更新页面时,只需这样做。
Obx(() => Text("${controller.name}"));

Riverpod

ini 复制代码
final fristNameProvider = StateProvider<String>((ref) => 'Tom');
final secondNameProvider = StateProvider<String>((ref) => 'Joy');
final fullNameProvider = StateProvider<String>((ref) {
  final fristName = ref.watch(fristNameProvider);
  final secondName = ref.watch(secondNameProvider);
  return '$fristName  $secondName';
});

//更改值得时候
 ref.read(fristNameProvider.notifier).state =
                     'Jane'
 ref.read(secondName.notifier).state =
                     'BB'

2、使用ConsumerWidget更新UI

ref.read(surnameProvider) 读取某个值

ref.read(nameProvider.notifier).state 更新某个值的状态

scala 复制代码
class MyHomePage extends ConsumerWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) => 
     Scaffold(
        appBar: AppBar(
          title: const Text('Riverpod Example'),
        ),
        body: Text(
               ref.watch(fullNameProvider),
               style: Theme.of(context).textTheme.headlineMedium,
            ),
      );
}

这里Consumer组件是与状态交互所必需的,Consumer有一个非标准build方法,这意味着如果您需要更改状态管理解决方案,您还必须更改组件而不仅仅是状态。

RxDart

RxDart将ReactiveX的强大功能引入Flutter,需要明确的逻辑来组合不同的数据流并对其做出反应。

存储计算值:它不会以有状态的方式直接存储计算值,但它确实提供了有用的运算符(例如distinctUnique)来帮助您最大限度地减少重新计算。

RxDart 库还有一个流行的类型被称为BehaviorSubject。响应式编程试图解决的核心问题是当依赖图中的任何值(依赖项)发生变化时自动触发计算。如果有多个可观察值,并且您需要将它们合并到计算中,Rx 库自动为我们执行此操作并且自动最小化重新计算以提高性能。

该库向 Dart 的现有流添加了功能。它不会重新发明轮子,并使用其他平台上的开发人员熟悉的模式。

1、监听

ini 复制代码
 final fristName = BehaviorSubject.seeded('Tom');
 final secondName = BehaviorSubject.seeded('Joy');
 
 /// 更新值
  fristName.add('Jane'),
  secondName.add('Jane'),

2、使用StreamBuilder更新UI

less 复制代码
 StreamBuilder<String>(
        stream: Rx.combineLatest2(
            fristName,
            secondName,
            (fristName, secondName) => '$fristName $secondName',
             ),
             builder: (context, snapshot) => Text(
               snapshot.data ?? '',
               style: Theme.of(context).textTheme.headlineMedium,
              ),
    ),

Signals

Signals以其computed功能介绍了一种创新、优雅的解决方案。它会自动创建反应式计算,当任何依赖值发生变化时,反应式计算就会更新。

1、监听

dart 复制代码
  final name = signal('Jane');
  final surname = signal('Doe');
  late final ReadonlySignal<String> fullName =
      computed(() => '${name.value} ${surname.value}');
  late final void Function() _dispose;

 @override
  void initState() {
    super.initState();
    _dispose = effect(() => fullName.value);
  }

2、使用watch更新UI

less 复制代码
Text(
    fullName.watch(context),
    style: Theme.of(context).textTheme.headlineMedium,
 ),
相关推荐
jhonjson16 小时前
Flutter开发之flutter_local_notifications
flutter·macos·cocoa
iFlyCai17 小时前
23种设计模式的Flutter实现第一篇创建型模式(一)
flutter·设计模式·dart
恋猫de小郭18 小时前
Flutter 小技巧之 OverlayPortal 实现自限性和可共享的页面图层
flutter
A_cot1 天前
Vue.js:构建现代 Web 应用的强大框架
前端·javascript·vue.js·flutter·html·web·js
B.-1 天前
在 Flutter 应用中调用后端接口的方法
android·flutter·http·ios·https
️ 邪神1 天前
【Android、IOS、Flutter、鸿蒙、ReactNative 】约束布局
android·flutter·ios·鸿蒙·reactnative
pinkrecall20121 天前
flutter调试
flutter
jhonjson1 天前
在Flutter中,禁止侧滑的方法
前端·javascript·flutter
️ 邪神2 天前
【Android、IOS、Flutter、鸿蒙、ReactNative 】文本点击事件
flutter·ios·鸿蒙·reactnative·anroid
️ 邪神2 天前
【Android、IOS、Flutter、鸿蒙、ReactNative 】文本Text显示
flutter·ios·鸿蒙·reactnative·anroid