当前位置: 首页 > 知识库问答 >
问题:

颤振未来与未来子类型错误?

吕飞翼
2023-03-14

我刚刚更新了Flutter,并成功地从git下载了我的原始项目。现在我得到了一个奇怪的Future错误。我在github上看到有人提到它,但没有关于如何修复的明确答案。项目甚至不加载。它从我的main.dart文件中读取Future语句并返回此...

[VERBOSE-2:dart\u error.cc(16)]未处理的异常:类型“Future dynamic”不是类型“Future String”的子类型,其中
Future来自dart:async
Future来自dart:async
String来自dart:core

***不确定错误在哪里。我的dart分析说“只等待未来”。这是我的未来代码,在我的小部件开始构建之前运行。。。

Future<Null> getData() async{
    FirebaseUser user = await FirebaseAuth.instance.currentUser;
    user = FirebaseAuth.instance.currentUser;
    var userid = user.uid;
    fb.child('users/${userid}').onValue.listen((Event event) {
      if (event.snapshot.value != null) {
        name = event.snapshot.value['displayName'];
        image = event.snapshot.value['image'];
      } else {
        name = "User";
      }
    });
  }

共有1个答案

庄博厚
2023-03-14

好的。我想我明白了。

Dart 1.0是一种软类型语言

main() async {  
  print(await getData()); 
}

Future<Null> getDatare() async{return "a";} 

会打印“a”

问题是Dart 2.0是一种类型化语言,所以未来实际上是有意义的。这里发生的事情(简而言之)是Future变成了FutureNull,您无法从FutureNull中获取字符串(因为它只包含Null)。

事实上,这类东西曾经咬过我[1],但如果你仔细想想,它是有道理的。请看以下代码:

List<dynamic> l = ["a", "b", "c", "d"];
List<String> d = l;

甚至更是如此

List<int> l = [1,2,3,4];
List<double> d = l;

将在颤振中崩溃。为什么?因为想想这里发生了什么:

什么是“l”?

----------------------
| int | int | int | int |
----------------------

什么是“d”?

---------------------------------------------
| double | double | double | double |
---------------------------------------------

那么如何在“l”和“d”之间转换呢?

您必须创建一个新的double列表,然后复制l中的值,将其转换为double,然后将其存储在“d”中。

但这不仅仅适用于列表。它适用于所有泛型。

当你有类似A的东西时

以下面的代码为例:

class Box<T> {
  T a;
  Box(T v) {
    a=v;
  }
  T getVal() {
    return a;
  }
  }

现在将Box转换为Box。这说不通,对吧?我能做到以下几点吗?

Box<int> i = new Box(5);
Box<String> s= new Box("a");
i + (s as Box<int>)

所以这里真正发生的事情是Box变成BoxInt,Box变成BoxString(编译器查找/替换标识符“T”为“int”或“T”为“String”)。

所以你在这里有同样的事情:你必须从未来解压价值,然后处理它。在你的情况下(实际上,你的情况有一个额外的问题——你没有返回任何东西),你可能想要一个未来,然后等待那个未来并得到一个字符串。

[1]. 它是怎么咬我的?来自Kotlin(或任何其他JVM语言),我已经习惯了能够做以下事情:

List<A> a = ...;
List<B> b = a;

没问题。为什么?因为JVM没有真正的泛型。它的作用被称为“类型擦除”,实际发生的情况是:

List<Object> a = ...;
List<Object> b = a;

这显然是可行的,因为所有Lists都有一个指向对象的指针,该指针是在运行时确定的。

这是因为Java1.0(与Dart不同)从来没有泛型,而且它们是固定的,因此为了向后兼容,它们使泛型的类型安全性比它们可能的要低。

因此,Dart(或C或Rust或Go数组)将泛型视为单态,而Java将它们视为多态代码(将T视为指针)。

 类似资料: