在 Flutter 中,为了在我们自己的包的 lib 目录中导入库,我们是否应该使用相对导入
import 'foo.dart'
Run Code Online (Sandbox Code Playgroud)
或包导入?
import 'package:my_app/lib/src/foo.dart'
Run Code Online (Sandbox Code Playgroud)
Dart 指南提倡使用相对导入:
在您自己的包的 lib 目录中导入库时,首选相对路径。
- 始终使用包导入。例如:
import 'package:my_app/my_code.dart';
除了简洁之外还有区别吗?为什么包导入会减少相对导入的错误?
我仍然在关注 flutter 中的状态管理技术,并且对何时以及为什么使用Provider.of<X>vs. Consumer<X>. 我从文档中了解到(我认为)在这两者之间进行选择时,当我们想要访问数据时,您将使用 Provider.of,但您不需要更改 UI。因此,以下(取自文档)可以访问数据并在新事件上更新 UI:
return HumongousWidget(
// ...
child: AnotherMonstrousWidget(// <- This widget will rebuild on new data events
// ...
child: Consumer<CartModel>(
builder: (context, cart, child) {
return Text('Total price: ${cart.totalPrice}');
},
),
),
);
Run Code Online (Sandbox Code Playgroud)
然而,在这里我们只需要在数据上不希望与UI重建,我们会使用Provider.of<X>与listen参数集false,如下图所示:
Provider.of<CartModel>(context, listen: false).add(item); \\Widget won't rebuild
Run Code Online (Sandbox Code Playgroud)
但是,listen不是必需的,因此以下内容也将运行:
Provider.of<CartModel>(context).add(item); \\listener optional
Run Code Online (Sandbox Code Playgroud)
所以这给我带来了几个问题:
Provider.of<X>和的正确方法吗Consumer<X>?前者不更新用户界面,后者呢?listen未设置为false默认情况下会重建小部件还是不重建?如果listen设置为true呢?在搜索 Flutter 的依赖注入解决方案时,我发现了两个很棒的库:provider和get_it.
据我所知provider,它有更多的样板文件,但它非常适合 Flutter ,一旦注入的值发生变化,就Consumer可以重建Widget树的一部分。
get_it 另一方面更直接,更容易使用,并且不依赖于 Flutter,因此可以与任何 Dart 代码一起使用。
它们之间还有什么区别和限制吗?我知道这有点自以为是,但 Flutter 太新了,所以最好公开注册好处、副作用和陷阱。
dependency-injection service-locator flutter flutter-provider
我无法将多个消费者用于具有提供程序的单个小部件?假设我的小部件是 CurvedNavigationBar 并且我在该小部件中有 4 个项目。我还有 4 个不同的类,它们扩展了 ChangeNotifier 并负责 CurvedNavigationBar 中的每个项目。
如何在单个小部件中收听这 4 个更改通知程序?我查看了文档并找不到这样的示例..这甚至可能吗?我发现 Consumer 有一个 builder 方法,所以这意味着你只能构建一个小部件一次/并听一次它。
我是否应该拥有一个扩展 ChangeNotifier 的类,然后更新该小部件中的值并仅使用一个 Consumer 来侦听更新的值?
我想加载事件列表并在获取数据时显示加载指示器。
我正在尝试提供者模式(实际上是重构一个现有的应用程序)。
因此,事件列表的显示取决于提供程序中管理的状态。
问题是当我打电话notifyListeners()太快时,我得到这个异常:
????????? 基础库捕获的异常 ????????
为 EventProvider 分派通知时抛出以下断言:
在构建期间调用 setState() 或 markNeedsBuild() 。
...
EventProvider 发送通知是:“EventProvider”的实例
??????????????????????????????????????????
在调用notifyListeners()解决问题之前等待几毫秒(请参阅下面提供程序类中的注释行)。
这是一个基于我的代码的简单示例(希望不要过于简化):
主要功能:
Future<void> main() async {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => LoginProvider()),
ChangeNotifierProvider(create: (_) => EventProvider()),
],
child: MyApp(),
),
);
}
Run Code Online (Sandbox Code Playgroud)
根小部件:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final LoginProvider _loginProvider = Provider.of<LoginProvider>(context, listen: true);
final EventProvider _eventProvider = Provider.of<EventProvider>(context, listen: false);
// load user …Run Code Online (Sandbox Code Playgroud) 我正在使用 Provider(提供程序:3.0.0+1)开发 Flutter 应用程序。我正在使用带有控制器的 StreamProvider 的 MultiProvider。但我总是收到错误。
下面是我的代码
main.dart
Widget build(BuildContext context) {
return MultiProvider(
providers: [
StreamProvider<RecipeStreamService>.value(value: RecipeStreamService().controllerOut)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Home Food',
routes: {
'/register': (BuildContext context) => RegisterPage(),
'/login': (BuildContext context) => LoginPage()
},
theme: ThemeData(
primaryColor: Colors.lightBlue[300],
accentColor: Colors.green[300],
textTheme: TextTheme(
headline: TextStyle(fontSize: 42.0, fontWeight: FontWeight.bold, color: Colors.black54),
title: TextStyle(fontSize: 22.0, fontStyle: FontStyle.italic),
body1: TextStyle(fontSize: 18.0),
button: TextStyle(fontSize: 20.0,fontWeight: FontWeight.normal, color: Colors.white)
)
),
home: HomePage(title: 'Home'),
),
);
}
Run Code Online (Sandbox Code Playgroud)
RecipeStreamService.dart
class RecipeStreamService …Run Code Online (Sandbox Code Playgroud) 我想在我的颤振项目中使用提供程序包(4.0),但我收到“试图使用具有可听/流子类型的提供程序”错误/警告。
我的星座:
我有一个Api()包含用于 firebase-cloudstorage 的基本 CRUD 功能的类。
我有一个EventService()-class,它使用Api()带有具体参数的-class。
对于我的观点,我有一个EventOverviewModel使用 EventService的 ViewModel 类。
我的提供程序配置如下所示:
List<SingleChildWidget> providers = [
...independentServices,
...dependentServices,
...uiConsumableProviders,
];
// Services die unabhängig von anderen sind
List<SingleChildWidget> independentServices = [
Provider<EventService>(create: (_) => EventService(api: Api('events')))
];
// Services die von anderen Services abhängig sind
List<SingleChildWidget> dependentServices = [
ProxyProvider<EventService, EventOverviewModel>(
update: (_, srvc, __) => EventOverviewModel(eventService: srvc),
)
];
List<SingleChildWidget> uiConsumableProviders = [];
Run Code Online (Sandbox Code Playgroud)
一切似乎都在应用程序中工作,但无论如何我都得到了“尝试使用具有可听/流子类型的提供程序”。
我应该如何更改我的代码以不再收到此错误消息?
Running Gradle task 'assembleDebug'...
I/flutter …Run Code Online (Sandbox Code Playgroud) 我在一个小部件树中有一个 FloatingActionButton ,它有一个BlocProviderfrom flutter_bloc。像这样的东西:
BlocProvider(
builder: (context) {
SomeBloc someBloc = SomeBloc();
someBloc.dispatch(SomeEvent());
return someBloc;
},
child: Scaffold(
body: ...
floatingActionButton: FloatingActionButton(
onPressed: _openFilterSchedule,
child: Icon(Icons.filter_list),
),
)
);
Run Code Online (Sandbox Code Playgroud)
这将打开一个模态底部工作表:
void _openFilterSchedule() {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return TheBottomSheet();
},
);
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试SomeBloc使用BlocProvider.of<SomeBloc>(context)inside访问,TheBottomSheet但出现以下错误:
BlocProvider.of() called with a context that does not contain a Bloc of type SomeBloc.
Run Code Online (Sandbox Code Playgroud)
我曾尝试使用/sf/answers/3957352801/ 中描述的解决方案,但仅适用于BottomSheet而不适用于ModalBottomSheet。
注意:这不限于BlocProvider或 …
Provider 包使用InheritedWidget. 当我在对话框中时想访问提供程序时,这是一个问题。如果我使用加载对话框
showDialog(... builder: (context) => MyDialog);
Run Code Online (Sandbox Code Playgroud)
我无法访问任何东西,InheritedWidget因为我的对话框不是主小部件树的一部分。这也意味着我无法访问我的 Provider 提供商,对吗?
我的问题是:如果它不是主应用程序小部件树的一部分,我如何在对话框中访问我的提供程序?
final firebaseAuth = Provider.of<FirebaseAuth>(context);
Run Code Online (Sandbox Code Playgroud)
我在使用BLoCs. 如果我尝试在对话框中通过 检索它们InheritedWidget,它们将失败。我已经通过BLoC在构造函数中传递了来解决这个问题,但这似乎违背了InheritedWidgets.
我需要从 Firebase Cloud Firestore 获取 1 个字段 1 次。如何通过 Widget 构建之外的提供者来实现此目的?
以下是我的组合提供商。appStartupProvider是一个 FutureProvider,我想bool从 firestore 中的这个 1 字段中获取值。但是,状态中的等待appStartupProvider“'await'应用于'AsyncValue',这不是'Future'”。
final accountStreamProvider = StreamProvider<Account>((ref) {
final database = ref.watch(databaseProvider);
return database != null ? database.accountStream() : const Stream.empty();
});
final _accountSetupCompleteProvider = Provider<AsyncValue<bool>>((ref) {
return ref
.watch(accountStreamProvider)
.whenData((account) => account?.accountSetupComplete ?? false);
});
final appStartupProvider = FutureProvider<bool>((ref) async {
final accountSetupComplete = await ref.watch(_accountSetupCompleteProvider);
return accountSetupComplete;
});
Run Code Online (Sandbox Code Playgroud)
显然,这里缺少一些有关组合提供程序和 AsyncValue 的关键知识,但我正在尝试实现RiverPod 组合提供程序页面上所述的情况,我在其中看到正在使用等待。