易於理解的反應性狀態管理解決方案。
狀態在實施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}