【问题标题】:Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Future<dynamic>'未处理的异常:类型 '_InternalLinkedHashMap<String, dynamic>' 不是类型 'Future<dynamic>' 的子类型
【发布时间】:2019-08-25 18:54:06
【问题描述】:

我收到错误消息:

Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Future <dynamic>`
_LocationScreenState.build.<anonymous closure> 
(package:clima/screens/location_screen.dart:71:32) 
<asynchronous suspension>

被精确定位的线在这个里面:

FlatButton(
   onPressed: () async {
     var weatherData = await weather.getLocationWeather();
     updateUI(weatherData); //<==it's this line
                    },

weather.getLocationWeather() 返回一个 Future&lt;dynamic&gt;. 类型的变量,它是 JSON,并且在调试器中对其进行评估,它是预期的 JSON。 upDateUI() 方法开始

  void updateUI(Future<dynamic> weatherDataFuture) async {
    final weatherData = await weatherDataFuture;

然后继续解析生成的weatherData。它在程序的早期被调用并按预期工作。我确信这个问题与我永无止境但仍在继续努力理解异步编程有关:-)

【问题讨论】:

  • weather.getLocationWeather() 值是“_InternalLinkedHashMap”,并且似乎“updateUI(Future)”返回的结果与“weather.getLocationWeather()”相同
  • @NorbertoMartínAfonso -- 感谢您的回复!我不确定我是否完全理解。我了解 weather.getLocationWeather() 显然返回类型“_InternalLinkedHashMap”。但是 updateUI() 是无效的;它不返回任何东西(?)。
  • 试试我的答案 我已编辑并返回地图值

标签: asynchronous flutter dart


【解决方案1】:

await weather.getLocationWeather() 获取由getLocationWeather 返回的未来,并等待它完成一个值。该值是一个地图。

然后,您使用该映射值调用updateUI,即使它期待未来。该变量的类型为dynamic,因此您不会收到静态警告,只会收到运行时错误。

   onPressed: () async {
     var weatherData = await weather.getLocationWeather();
     updateUI(weatherData); //<==it's this line

尝试删除await。那么weatherData 将是Future&lt;dynamic&gt;,这正是updateUI 所期望的类型。 (然后您也可以从函数中删除async)。

【讨论】:

  • 您的建议解决了这个问题,谢谢!我完全理解它,它还有一个额外的好处是帮助我更好地理解另外两个人的建议,他们很友好地做出了回应。
  • 我想我很困惑,因为在(这篇文章)的结尾[medium.com/flutter-community/…作者写道“......当你选择等待未来时,必须将函数标记为异步,因此所有必须等待谁调用它,并且必须将它们标记为异步..."
【解决方案2】:

试试这个:

final weatherData;
Future<Map<String, dynamic>> weatherDataFuture async{
  return weather.getLocationWeather();
}

FlatButton(
  onPressed: () {
  weatherDataFuture.then((value){
   weatherData=value.values;
 });
} 
) 

【讨论】:

  • 感谢您编辑后的回复(欢迎来到 SO :-) ... 我在理解您的代码方面有点吃力,可能是因为我是初学者。对我来说,weatherDataFuture 只是一个参数名称。如果我在onPressed() 方法中按原样使用它,我确信我会收到关于未声明变量的错误。也许我也应该在我的原始帖子中澄清weatherDataonPressed()updateUI() 方法中的不同变量。这对我来说是错误的变量命名。
  • 非常感谢。我认为您想将某个数据库中的数据提供给最终变量。然后你需要一个 Future 来等待数据,当你按下 FlatButton 时,数据将发送到最终变量。代码中使用Future.then((value))时,等待的是数据(value),当数据存在“then”时,可以将“Map.values”设置为最终变量weatherData。
【解决方案3】:

获取数据的返回值需要进行强制转换。我建议查看 Flutter 文档中的 JSON 教程。

    FlatButton(
       onPressed: () async {
         var weatherData = Map<String, dynamic>.from(await weather.getLocationWeather());
         updateUI(weatherData); //<==it's this line
    },
void updateUI(Map<String, dynamic> weatherData) async {
    ...

===== 基于 cmets 编辑 =====

FlatButton(
    onPressed: () async {
      var weatherData = SynchronousFuture(Map<String, dynamic>.from(await weather.getLocationWeather()));
      updateUI(weatherData); //<==it's this line
},
void updateUI(Future<Map<String, dynamic>> weatherData) async {
    ...

【讨论】:

  • 非常感谢您的回复。更改 weatherData 声明将在下一行产生错误,告诉我参数类型“列表”不能分配给“未来”类型的参数。
  • 它可能需要转换为Map,而不是List
  • 抱歉,这就是我尝试在手机上回答问题时得到的结果。因此,现在在将其交给updateUI 之前解决了未来,您可以更新updateUI 以便它需要Map&lt;String, dynamic&gt;
  • 是的,这种改变是有道理的并且是适当的(就像你上周友好回答的我的问题一样 :-) 事实上,我很想告诉你把它留给未来的人来到这里。对我来说,我在原始帖子中没有说的是 updateUI() 在其他地方被调用(没有问题),所以你建议的更改最终会破坏其他代码。
  • 听起来可能需要进行一些重构 :) 但是您可以暂时将已转换的 Map 包装在 FutureSynchronousFuture 中。
猜你喜欢
  • 2020-08-20
  • 2020-07-14
  • 1970-01-01
  • 2021-02-11
  • 2021-07-11
  • 2021-09-20
  • 2021-05-05
  • 1970-01-01
相关资源
最近更新 更多