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,
 ),
相关推荐
江上清风山间明月8 小时前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能18 小时前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人19 小时前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen19 小时前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang1 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang1 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1231 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-1 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力2 天前
Flutter应用开发:对象存储管理图片
flutter