易于理解的反应性状态管理解决方案。
状态在实施ValueNotifier的一个或多个Value或类似类的实例中举行。这些是每个人都从TextEditingController , Animation等中知道的标准颤动界面。
此外,您可以使用ListValue和MapValue来创建可观察的List和Map值,这些列表可以通知您有关细粒度更改事件的通知(而不是整个值更改)。
当ValueNotifier (或任何Listenable )触发通知时, AutoBuild会自动重建小部件。它类似于Flutter的ValueListenableBuilder ,但它可以跟踪多种依赖性,并且还可以使用Listenable 。
无需致电addListener / removeListener 。只需直接get() AutoBuild时的值,请注意跟踪您的依赖项。
与InheritedWidget和Provider不同,您可以对重建的内容进行精细的控制。
标准的幻影类,例如TextEditingController和Animation实现ValueListenable ,因此可以与AutoBuild建立良好。
DerivedValue是从其他可观察值计算(得出)的可观察值。
此外, ListValue和MapValue提供了.map()和其他操作,以创建派生容器,以使自己以每元件为单位进行更新。
最终的代码比集合或REDUX中的同一解决方案要简单得多。
StreamBuilder ,没有窗口小部件的异步加载(除非您真的需要它)。switch()语句的事件处理程序。 注意:另请参见参考。
一个简单的AutoBuild示例:
import 'package:flutter/material.dart' ;
import 'package:reactive_state/reactive_state.dart' ;
class MyPage extends StatelessWidget {
MyPage ({ Key key, @required this .counter}) : super (key : key);
final ValueNotifier < int > counter;
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (title : Text ( 'Counter' )),
body : Column (
children : < Widget > [
AutoBuild (builder : (context, get , track) {
return Text ( 'Counter: ${ get ( counter )}' );
}),
MaterialButton (
onPressed : () => counter.value ++ ,
child : Text ( 'Increment' ),
),
],
),
);
}
}请注意,在实际应用程序中,您不应该直接将状态变为状态,而是将其放入单独的方法中,例如通过提供商软件包访问的对象。
另外,请查看回购中的示例。
在小部件之外,您可能仍然需要对状态变化做出反应。您可以使用autoRun()和AutoRunner (有关详细信息请参阅参考)来执行此操作。
作为ValueNotifier的替代方案,您还可以使用reactive_state的Value类,该类别提供了一个update()方法来修改更复杂的对象:
class User {
String name = '' ;
String email = '' ;
// ...
}
var userValue = Value ( User ());
userValue. update ((user) {
user.name = 'Adam' ;
user.email = '[email protected]' ;
});这类似于使用StatefulWidget调用setState() 。使用update()您可以更改多个属性,并且Value将触发单个通知后,即使没有更改任何更改(因此您不需要实现复杂对象的比较操作员)。
DerivedValue是一个动态计算的ValueListenable ,每当其依赖性变化时都会更新其值:
var user = Value ( User ());
var emailLink = DerivedValue (( get , track) => 'mailto:${ get ( user ). email }' );在这里,可以自行观察emailLink ,并在修改user时会更新。
一个简单的示例,显示一些可以完成的事情:
final listValue = ListValue ( < int > []);
final mappedList = listValue. map ((x) => x. toString ());
final listToMap = mappedList. toMap ((x) => MapEntry ( 2 * int . parse (x), x));
final invertedMap = listToMap. map ((k, v) => MapEntry (v, k));
listValue. addAll ([ 4 , 1 ]);
// => invertedMap.value == {'4': 8, '1': 2}