我已经在我的应用程序中实现了用于状态管理的 Provider。现在,我需要在加载屏幕后在类中添加一些数据。
我怎么能做到这一点?
stepInfo.addToList = new VaccStep(); // Need to call it one time once screen is loaded.
Run Code Online (Sandbox Code Playgroud)
我试图从 initState 调用这个方法,但它给出了错误!!
class AdminAddVaccination extends StatefulWidget {
@override
State createState() => new AdminAddVaccinationState();
}
class AdminAddVaccinationState extends State<AdminAddVaccination> {
@override
void initState() {
super.initState();
var stepInfo = Provider.of<StepInfo>(context); // ERROR!!
stepInfo.addToList = new VaccStep(); // ERROR!!
}
Widget build(BuildContext context) {
return new ChangeNotifierProvider(
builder: (context) => StepInfo(),
child: ScreenBody(),
);
}
}
class ScreenBody extends StatelessWidget {
@override
Widget build(BuildContext …Run Code Online (Sandbox Code Playgroud) 我知道 flutter 中的 BLoC 就像 android 的 MVVM 中的 viewmodel 层,因此在配置更改时不会一次又一次地获取数据(例如:屏幕方向的更改)。
我很困惑提供者是替换 BLoC 模式中 RxDart 的功能还是替换角色 BLoC 模式本身。
此外,如果我根本不使用 BLoC,那么应用程序是否会在配置更改后继续存在。
请通过一些用例解释提供程序对 BLoC、RxDart 组合的限制。
我正在尝试使用StreamProvider(来自这个很棒的包),但我一直在努力让特定的流工作。
我创建了一个StreamController我用来Stream通过它的Sink. 所有这些似乎都运行良好。但是当将它Stream与 一起使用时StreamProvider,小部件树不会反映Stream. 但是,使用StreamBuilder.
使用的代码StreamProvider:
class TestPage extends StatelessWidget {
final Mockup exchange = ExchangeApi.mockup;
@override
Widget build(BuildContext context) {
return StreamProvider<List<Data>>(
builder: (BuildContext context) => Wrapper.mockup.stream,
initialData: null,
catchError: (BuildContext context, e) {
print("Error: $e");
return null;
},
child: TestPageBody(),
);
}
}
class TestPageBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
List<Data> dataList = Provider.of<List<Data>>(context);
return …Run Code Online (Sandbox Code Playgroud) 添加对的依赖项后ProfileLogic,LocationLogic应用程序启动时出现以下错误:
I/flutter(14674):一个LocationLogic被废弃后使用。
I/flutter (14674):一旦您在 LocationLogic 上调用了 dispose(),就不能再使用它。
这些是我的提供者:
providers: [
ChangeNotifierProvider(builder: (_) => ConnectivityLogic()),
ChangeNotifierProxyProvider<ConnectivityLogic, ProfileLogic>(
builder: (context, connectivity, previousMessages) =>
ProfileLogic(connectivity.isOnline),
initialBuilder: (BuildContext context) => ProfileLogic(false),
),
ChangeNotifierProxyProvider<ProfileLogic, LocationLogic>(
builder: (context, profileLogic, previousMessages) =>
LocationLogic(profileLogic.profile),
initialBuilder: (BuildContext context) => LocationLogic(null),
),
ChangeNotifierProvider(builder: (_) => SignUpModel()),
ChangeNotifierProxyProvider<ConnectivityLogic, WorkLogic>(
builder: (context, connectivity, previousMessages) =>
WorkLogic(connectivity.isOnline),
initialBuilder: (BuildContext context) => WorkLogic(false),
),
ChangeNotifierProvider(builder: (_) => OrderLogic()),
]
Run Code Online (Sandbox Code Playgroud)
奇怪的是,一切正常,即使有那个错误。
我目前正在处理一个问题,我需要来自 API 的一些数据才能将其显示到我的小部件中。我遵循了一些 Provider 架构模式,在那里你 setState 两次:
1- 获取数据时
2- 当数据已经被获取时
所以我目前正在处理的问题是,我的小部件抛出以下错误:
setState() or markNeedsBuild() called during build.
我知道这个错误是因为在构建过程中调用了 setState,但是..如何在构建过程中获取我的 api,然后将它显示给我的小部件?这是我的代码:
NewsPage.dart
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
SideBarWidget _sidebar;
@override
void initState() {
Provider.of<HomeViewModel>(context, listen: false)
.fetchUltimaNoticia(context); --> ****Data to get fetched****
_sidebar = const SideBarWidget();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('INICIO'),
centerTitle: true,
automaticallyImplyLeading: false,
leading: Builder(
builder: (context) => …Run Code Online (Sandbox Code Playgroud) I am new to flutter and especially provider pattern. I went through the documentation, examples and some tutorials for the provider pattern statemanagement and i am trying to implement it in one of my projects. I am developing a personal expenses manager app. The problem is that all the documentation, examples and tutorials assume the model provider has all the required data available in memory, that is, all the mock data is already there in a list. It is fairly …
当我知道状态正在发生变化时,我的应用程序的用户界面不会更新。我正在使用watchRiverpod 的方法来处理此问题,但除非我进行热重载,否则更改不会生效。
我有一个类,HabitListStateNotifier其中包含从列表中添加/删除习惯的方法:
class HabitListStateNotifier extends StateNotifier<List<Habit>> {
HabitListStateNotifier(state) : super(state ?? []);
void startAddNewHabit(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (_) {
return NewHabit();
});
}
void addNewHabit(String title) {
final newHabit = Habit(title: title);
state.add(newHabit);
}
void deleteHabit(String id) {
state.removeWhere((habit) => habit.id == id);
}
}
Run Code Online (Sandbox Code Playgroud)
这是这个的提供者:
final habitsProvider = StateNotifierProvider(
(ref) => HabitListStateNotifier(
[
Habit(title: 'Example Habit'),
],
),
);
Run Code Online (Sandbox Code Playgroud)
HabitList以下是(UI 未更新的部分)的实现方式:
class HabitList extends ConsumerWidget {
@override
Widget build(BuildContext context, …Run Code Online (Sandbox Code Playgroud) 基本上,我想将初始构造函数值设置为,StateProvider以便我可以在其子小部件中使用它。
final stateProvider = StateProvider((ref) => "default");
class ExampleWidget extends ConsumerWidget {
ExampleWidget({required String text}){
// how to override default hear as
// stateProvider = text
}
@override
Widget build(BuildContext context, ScopedReader watch) {
return Column(
children: [
Text(watch(stateProvider).state),
Container(
child: ChildWidget(),
),
],
);
}
}
class ChildWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, ScopedReader watch) {
return Container(
child: Text(watch(stateProvider).state),
);
}
}
Run Code Online (Sandbox Code Playgroud)
那么我该如何实现呢?
我已经尝试过,但状态值没有更新。
编辑 - - - - - - - …
当我们使用访问 Bloc 对象时,如果当前上下文的祖先小部件BlocProvider.of<OrderBloc>(context)不存在,它将返回异常。OrderBloc返回的异常如下:
No ancestor could be found starting from the context that was passed to BlocProvider.of<OrderBloc>().
Run Code Online (Sandbox Code Playgroud)
但当祖先小部件上不存在时,我希望返回null而不是异常。OrderBloc考虑以下场景:
var orderBloc = BlocProvider.of<OrderBloc>(context);
return Container(child: orderBloc == null
? Text('-')
: BlocBuilder<OrderBloc, OrderState>(
bloc: orderBloc,
builder: (context, state) {
// build something if orderBloc exists.
},
),
);
Run Code Online (Sandbox Code Playgroud) 我有一个非常大、复杂的应用程序,有很多页面,其中输入表单有很多字段(文本、日期选择、组合框……),所以状态相当大。我正在从 Provider 切换到 Riverpod,并且建议的状态管理方式似乎主要是 StateNotifierProvider。但该状态是不可变的,这意味着您必须在每次更改时克隆完整的状态。我需要的是 Providers ChangeNotifierProvider(Riverpod 也有),以便能够拥有可变状态并更好地控制何时触发侦听器的重建。但 Riverpod 不鼓励使用 ChangeNotifierProvider,这让我有点紧张。也许我并没有真正理解 StateNotifierProvider 的概念。
那么问题是,如何使用 StateNotifierProvider 来处理复杂的状态?真的有必要总是克隆状态吗?
编辑:复杂是指更多的字段(例如 50)以及列表和对象结构。你可以克隆它,但它很昂贵,而且在每一个小变化上都这样做感觉不自然/明智。这真的是预期的方式吗?有没有办法在仍然使用 StateNotifierProvider 的情况下进行克隆?
flutter-provider ×10
flutter ×9
dart ×3
riverpod ×3
bloc ×2
flutter-bloc ×1
setstate ×1
state ×1