Легкое понимание реактивного решения для управления состоянием для трепета.
Состояние проводится в одном или нескольких случаях Value или аналогичных классов, внедряющих ValueNotifier . Это стандартные интерфейсы Flutter, которые все знают из TextEditingController , Animation и т. Д.
Кроме того, вы можете использовать ListValue и MapValue для создания наблюдаемых значений List и Map , которые могут уведомить вас о мелкозернистых событиях изменения (вместо изменения всего значения).
AutoBuild автоматически восстанавливает ваши виджеты, когда ValueNotifier (или любой Listenable ) запускает уведомление. Он похож на ValueListenableBuilder от Flutter, но он может отслеживать множество зависимостей, а также работает со 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 вы также можете использовать класс Value reactive_state , который предоставляет метод update() для изменения более сложных объектов:
class User {
String name = '' ;
String email = '' ;
// ...
}
var userValue = Value ( User ());
userValue. update ((user) {
user.name = 'Adam' ;
user.email = '[email protected]' ;
}); Это похоже на вызов setState() с StatefulWidget . С помощью 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}