потребитель является ссылкойreact-consumerспособ управления состоянием, используя дартсStream
Опубликуйте подписку.
Для реактивоподобных проектов, когда проект достигает определенного уровня, менеджер состояний незаменим, во Flutter есть много библиотек управления состояниями, BLOC, Provider, redux и т. д., но их существующая проблема в том, что они не обеспечивают очень удобного управления состояниями. , Оптимизация.
Особенность Consumer заключается в том, что это только режим публикации-подписки плюс StateFulWidget, который имеет преимущество перед менеджером состояний, инкапсулированным на основе InheritedWidget на рынке, в том, что он не требует пакета режима провайдера верхнего уровня. Исходя из этого, потребитель может облегчить проекту создание независимого управления состоянием подмодулей.Конечно, можно использовать и единый режим потребителя для управления состоянием всего проекта.
В соответствии с этой предпосылкой мы обнаружим, что если проект достаточно велик, нам нужно разделить управление несколькими подсостояниями или какое-то локальное управление состоянием, что может эффективно уменьшить объем диспетчеризации событий и повысить производительность; еще одна особенность потребителя — это Обязательное использование Потребитель описывает объекты, используемые каждой подпиской, поэтому потребитель может помочь оптимизировать производительность и заблокировать ненужные обновления.
Feature
- Потребителю не нужен объект-оболочка Provider верхнего уровня;
- Потребители могут легко настроить независимое управление состоянием для подмодулей;
- потребительское использование
memo
Блокировать ненужные обновления, вдохновленные react.Hooks; - Consumer очень прост в использовании всего с 3 API:
- getState
- setState
- build
Документация по API:
установить потребителя
Исправлятьpubspec.yaml
:
dependencies:
consumer: ^1.0.2
Начиная
Это проект инициализации Flutter по умолчанию. Мы используем потребитель, чтобы преобразовать его, удалить StateFulWidget и заменить на StatelessWidget:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
// *** 定义一个类,描述状态 ***
class ExampleState {
int counter = 0;
}
// *** 创建一个 consumer ***
var consumer = Consumer(ExampleState());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Consumer Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
_incrementCounter() {
// *** 使用 setState ,触发订阅的组件更新 ***
consumer.setState((state) => state.counter++);
}
@override
Widget build(BuildContext context) {
print('整个对象仅更新一次,更新时仅更新订阅的组件');
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
// *** 使用 consumer.build 订阅一个组件 ***
consumer.build(
memo: (state) => [state.counter],
builder: (ctx, state) {
print('仅有 memo 返回值中的对象改变了,builder 对象才会更新');
return Text(
'$state.counter',
style: Theme.of(context).textTheme.display1,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
FAQ
параметрmemo
Какова роль?
Если в вашем проекте много государственных подписок, используйтеmemo
может значительно улучшить производительность, поэтомуmemo
Дизайн как параметр, который необходимо определить.
memo
Концепция исходит из react.Hooks, который используется для описания объекта, который прослушивает изменения.Обновления будут отправляться только при изменении объекта.
Один из принципов заключается в том, какие свойства нам нужно использовать в объекте построителя,memo
Возвращаемый массив определяет, какие свойства, здесь у нас есть несколько примеров:
Если мы создадим два виджета с помощью Consumer.build:
// *** definition a state ***
class ExampleState {
List<String> animates = [];
int age = 0;
String name = 'dog';
}
// *** create a consumer ***
var consumer = Consumer(ExampleState());
Column(
children: <Widget>[
consumer.build(
memo: (state) => [state.age, state.animates],
builder: (ctx, state) {
print('Update when state.age change');
return Text(
'$state.age',
style: Theme.of(context).textTheme.display1,
);
},
),
consumer.build(
memo: (state) => [state.name],
builder: (ctx, state) {
print('Update when state.name change');
return Text(
state.name,
style: Theme.of(context).textTheme.display1,
);
},
),
],
);
Затем мы обновляем state.name:
consumer.setState((state){
state.name = 'cat';
});
На данный момент, когда мы обновляемstate.name
, только подписалсяmemo: (state) => [state.name]
Виджет будет обновлен, а обновления других виджетов будут перехвачены потребителем.
почему я использовалconsumer.setState
Виджет после этого не обновляется?
может быть выbuilder
используется вstate.name
, ноmemo
Возвращаемый массив не содержитstate.name
:
Center(
child: consumer.build(
memo: (state) => [state.age],
builder: (ctx, state) {
return Text(
state.name,
style: Theme.of(context).textTheme.display1,
);
},
),
);
может быть, твойmemo
Ничего не слушая:
Center(
child: consumer.build(
memo: (state) => [],
builder: (ctx, state) {
return Text(
state.name,
style: Theme.of(context).textTheme.display1,
);
},
),
);
Возможно, вы просто изменили объекты в списке или на карте, но не сбросили новый список или карту:
class ExampleState {
List<String> names = ['dog', 'cat'];
}
var consumer = Consumer(ExampleState());
Center(
child: consumer.build(
memo: (state) => [state.names],
builder: (ctx, state) {
return Text(
state.names[0],
style: Theme.of(context).textTheme.display1,
);
},
),
);
// 错误的更新:
Consumer.setState((state){
state.names[0] = 'fish'
});
// 正确的更新:
Consumer.setState((state){
List<String> names = [...state.names];
names[0] = 'fish'
state.names = names;
});
Государственные советы
Если вам нужно выполнить некоторые вычисления перед обновлением или упростить обработку обновлений, таких как массивы, вы можете создать некоторые свойства функции для состояния:
Вот пример изменения данных списка:
class ExampleState {
int lastChangeNamesIndex;
List<String> names = ['dog', 'cat'];
changeNameAt(int index, String name) {
lastChangeNamesIndex = index;
List<String> nextNames = [...names];
nextNames[index] = name;
names = nextNames;
}
}
var consumer = Consumer(ExampleState());
Center(
child: consumer.build(
memo: (state) => [state.names, state.lastChangeNamesIndex],
builder: (ctx, state) {
return Text(
state.names[state.lastChangeNamesIndex],
style: Theme.of(context).textTheme.display1,
);
},
),
);
// 轻松更新 names 和 lastChangeNamesIndex
consumer.setState((state){
state.changeNameAt(0, 'monkey');
})
That's all
Благодарим вас за чтение этого документа и использованиеconsumer
.