gpt4 book ai didi

Flutter get_it 和 FutureBuilder 不适用于热重载

转载 作者:行者123 更新时间:2023-12-04 15:39:37 26 4
gpt4 key购买 nike

下面的应用程序按预期工作,但不幸的是它不适用于热重载。我想知道如何使用它进行热重载。

所有代码所做的只是等待特定的 Future<String> 可用,然后在屏幕上显示该字符串。在等待期间,会显示一个进度指示器。

正如我所说,这按预期工作,但问题是如果我更改任何东西(我的意思是简单的装饰性东西)并且热重载开始,应用程序将永远坐在那里显示进度指示器,因为 connectionState 保持不变在 ConnectionState.waiting 模式下。

这是代码更详细的作用:

我在 String 中将一个 GetIt 对象注册为单例。由于该字符串包含在 Future 中,因此代码必须等待它准备好才能注册。

(在实际代码中,我从 Assets 中加载一个 JSON 字符串。这就是它在 Future 中的原因。)

FutureBuilder 通过等待 GetIt 向名为 readyFuture 的属性发送信号来等待字符串单例可用。

当字符串可用时,FutureBuilder 将其显示在屏幕上。在此之前,将显示 CircularProgressIndicator

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

GetIt locator = GetIt.instance;

void setupLocator() async {
final str = await Future<String>.delayed(Duration(seconds: 3), () => "hello");
locator.registerSingleton(str, signalsReady: true);
locator.signalReady(str);
}

void main() {
setupLocator();
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}

class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<void>(
future: locator.readyFuture,
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
Widget result;

switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
result = Center(child: CircularProgressIndicator());
break;
case ConnectionState.done:
if (snapshot.hasError)
result = Center(child: Text('Error: ${snapshot.error}'));
else
result = Center(child: Text('${locator.get<String>()}'));
break;
}

return result;
}
),
);
}
}

我的 pubspec.yaml 中有这些依赖项:

  get_it: ^3.0.1
provider: ^3.1.0

最佳答案

问题在于 GetIt 使用广播流 GetIt.ready 来表示它已准备就绪。广播流的问题是信号在热重载时丢失。

另一个单独的问题是,如果 GetIt.ready 广播流没有监听器,则就绪信号将丢失。因此这里存在竞争条件:您必须确保 FutureBuilder 在发送就绪信号之前正在监听 GetIt.ready,这通常是不可能的。

我想到的解决方法是使用 Completer 对象作为就绪信号。 (请参阅下面代码中的 locatorReady。)我向 GetIt.ready 添加了一个监听器,它向 Completer 对象发出信号。

FutureBuilder 等待 Completer.future 属性。

(我是一个 Flutter 新手,但在我看来,在 GetIt 中使用广播流并不是一个好的选择。我认为 Completer 会更好。)

这是更新后的代码:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

GetIt locator = GetIt.instance;
Completer<void> locatorReady = Completer<void>();

void setupLocator() async {
final str = await Future<String>.delayed(Duration(seconds: 8), () => "hello");
locator.registerSingleton(str, signalsReady: true);
locator.ready.listen((_){locatorReady.complete();});
locator.signalReady(str);
}

void main() {
setupLocator();
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}

class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<void>(
future: locatorReady.future,
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
Widget result;

switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
result = Text('Awaiting result ...');
break;
case ConnectionState.done:
if (snapshot.hasError)
result = Text('Error: ${snapshot.error}');
else
result = Text('Result: ${locator.get<String>()}');
break;
}

return Center(child: result,);
}
),
);
}
}

关于Flutter get_it 和 FutureBuilder 不适用于热重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58326960/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com