likes
comments
collection
share

Flutter中的ValueNotifier和ValueListenableBuilder

作者站长头像
站长
· 阅读数 15

今天,我们将使用ValueNotifier在不使用setState的情况下完成重建小部件。

在这篇文章中,我们将深入探讨ValueNotifier及其相应的主题。

ValueNotifier简介

ValueNotifier是继承自ChangeNotifier的一个类。该类可以保存单个值,并每当其持有值更改时会通知正在监听它的WidgetValueNotifier还是非常有用得,性能高效,因为它只重建使用ValueListenableBuilder监听它的Widget

ValueNotifier使用

将ValueNotifier视为保留值的数据流。我们为它提供一个值,每个监听器都会收到值变化的通知。 我们可以创建任何类型的int、bool、list或任何自定义数据类型的ValueNotifier。您可以像这样创建一个ValueNotifier对象:

ValueNotifier<int> counter = ValueNotifier<int>(0);

我们可以像这样更新值:

counter.value = counter.value++;
//或者
counter.value++;

此外,我们可以像这样监听ValueNotifier

counter.addListener((){
    print(counter.value);
});

删除值通知监听器

如果我们手动监听ValueNotifier,当前页面上不使用时,我们可以使用removeListener函数从ValueNotifier中手动删除侦听器。

ValueNotifier<int> valueNotifier = ValueNotifier(0);

void remove() {
  valueNotifier.removeListener(doTaskWhenNotified);
}

void add(){
  valueNotifier.addListener(doTaskWhenNotified);
}

void doTaskWhenNotified() {
  print(valueNotifier.value);
}

释放ValueNotifier

当不再使用时调用dispose方法是一个良好做法,否则可能会导致内存泄漏。ValueNotifier上的dispose方法将释放任何订阅的监听器。

@override
void dispose() {
    counter.dispose();
    super.dispose();
}

什么是ValueListenableBuilder?

Flutter中有许多类型的构建器,如StreamBuilderAnimatedBuilderFutureBuilder等,他们的名字表明他们是消费的对象类型。ValueListenableBuilder使用ValueNotifier对象,如果我们想在Widget中的监听某一个值,我们可以使用ValueListenableBuilder,每次我们收到值更新时,都会执行构建器方法。当我们路由到另一个页面时,ValueListenableBuilder会自动在内部删除监听。

const ValueListenableBuilder({
    required this.valueListenable,
    required this.builder,
    this.child,
})

这是ValueListenableBuilder的构造函数。在这里,valueListenable是要收听的ValueNotifier。构建器函数接收3个参数(BuildContext context, dynamic value, Widget child),该value是从提供的valueNotifier收到的数据。可以使用子参数。如果子构建成本高,并且不依赖于通知符的值,我们将使用它进行优化。

使用Value Notifier的计数器应用程序

使用ValueNotiferValueListenableBuilder的计数器应用程序,这里没有使用setState,当值发生改变的时候,我们只重建文本部分。

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _counterNotifier = ValueNotifier<int>(0);

  @override
  Widget build(BuildContext context) {
    print('HOMEPAGE BUILT');
    return Scaffold(
      appBar: AppBar(title: const Text('Counter App')),
      body: Center(
        child: ValueListenableBuilder(
          valueListenable: _counterNotifier,
          builder: (context, value, _) {
            return Text('Count: $value');
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _counterNotifier.value++;
        },
        child: const Icon(Icons.add),
      ),
    );
  }

  @override
  void dispose() {
    _counterNotifier.dispose();
    super.dispose();
  }
}