我Provider在我的 flutter 应用程序中使用,当我转到一个新页面时,Provider在第 2 页中无法访问提供给第 1页的数据。
我理解这种Provider工作方式的方式是,有一个中心位置可以存储所有数据,并且可以在应用程序的任何位置访问该数据。所以在我的应用程序中,如下所示,ToDoListManager是存储所有数据的地方。如果我在 中设置数据Page 1,那么我将能够在 中访问该数据Page 2,反之亦然。
如果这不正确,那么哪部分是错误的?为什么它在我的应用程序中不起作用?
这是代码
第 1 页
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
builder: (context) => ToDoListManager(),
child: Scaffold(
appBar: AppBar(
title: Text('Cool Project'),
),
body:e ToDoList(),
),
);
}
}
class ToDoList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final toDoListManager = Provider.of<ToDoListManager>(context);
return ListView.builder(
itemCount: toDoListManager.toDoList.length,
itemBuilder: (context, index) { …Run Code Online (Sandbox Code Playgroud) 我正在查看 flutter 网站上的以下代码:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => CartModel()),
Provider(create: (context) => SomeOtherClass()),
],
child: MyApp(),
),
);
}
Run Code Online (Sandbox Code Playgroud)
我想知道,Provider 和 ChangeNotifierProvider 有什么区别?
谢谢!
嘿,我有一个MultiProvider设置,它现在在点击 a 时抛出这个错误,TextField而在我实现多提供者之前却没有:
No Overlay widget exists above EditableText
错误文本没有给出代码中导致问题的任何有用指示,这是代码:
import 'package:***_mobile/Providers/user_auth_provider.dart';
import 'package:***_mobile/screens/browsing_page.dart';
import 'package:***_mobile/screens/film_details_page.dart';
import 'package:***_mobile/screens/login_screen.dart';
import 'package:***_mobile/screens/venue_details_page.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(***());
}
class *** extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => UserRepository.instance(),
child: Consumer(
builder: (context, UserRepository user, _) {
return MaterialApp(
title: 'Flutter Demo',
routes: {
'/browsing': (ctx) => BrowsingPage(),
'/venueDetails': (ctx) => VenueDetailPage(),
'/filmDetails': (ctx) => FilmDetailPage(),
'/login': (ctx) => LoginPage() …Run Code Online (Sandbox Code Playgroud) Pusher在我们的系统中,我们在我们的Admin Panel和mobile应用程序上使用,flutter我想用 和 包装整个应用程序屏幕,Pusher并在屏幕中Riverpod使用带有小部件的提供程序Hook,这意味着我想在我们拥有的所有屏幕上实现Pusher或广播接收main到MyApp的数据Pusher它们,基本上我们必须Pusher在需要接收数据的每个屏幕中使用,并且其难以维护应用程序,例如:
这个示例代码不正确,我尝试实现它,但我不能
在这里,您可以看到Pusher事件和侦听器工作正常,没有任何问题:
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): [BIND] new-login
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): [BIND] new-login
D/PusherClientPlugin( …Run Code Online (Sandbox Code Playgroud) 我在提供程序包的官方文档中找不到此内容 ,streamprovider 是否自动处理它们提供的流的处理,还是必须手动执行此操作?如果是这样,在哪里处理使用流提供程序公开的流的最佳实践是什么?
我已经成功设置了后台通知并使用邮递员对其进行了测试,一切都很好。
现在我需要在我的backgroundHandler 中访问Provider.of(context),它必须是没有上下文的静态方法。
我需要做的就是根据后台通知中的数据执行操作。
这是我初始化 FCM 的代码(我在启动屏幕中执行此操作)
Future<void> initFcm() async {
_firebaseMessaging.configure(
onBackgroundMessage: myBackgroundMessageHandler,
onMessage: (msg) async {
print('this is ONMESSAGE $msg');
},
onLaunch: (msg) async {
print('ON LAUNCH');
},
onResume: (msg) async {
print('ON RESUME');
},
);
// For testing purposes print the Firebase Messaging token
deviceToken = await _firebaseMessaging.getToken();
print("FirebaseMessaging token: $deviceToken");
}
static Future<dynamic> myBackgroundMessageHandler(
Map<String, dynamic> message) async {
print(message);
if (message.containsKey('data')) {
// Handle data message
final dynamic data = message['data'];
final orderId = data['order_id']; …Run Code Online (Sandbox Code Playgroud) 当我知道状态正在发生变化时,我的应用程序的用户界面不会更新。我正在使用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 ×10
flutter-provider ×10
dart ×6
riverpod ×4
bloc ×1
flutter-bloc ×1
pusher ×1
state ×1