You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何在Book工厂方法内直接获取关联Author数据?

问题描述

我有两类JSON响应数据:

书籍数据

{
"uuid": "c6514be0-cced-43b7-b1f4-e66256c1dcaf",
"title": "Harry Potter",
"author": "6637e87b-c2ce-4774-b812-4e8a09312a40"
}

作者数据(通过author字段与书籍关联)

{
"author": "6637e87b-c2ce-4774-b812-4e8a09312a40",
"name": "J.K. Rowling"
}

我已经定义了对应的Book和Author类:

class Book {
  final String uuid;
  final String title;
  final Author author;

  Book({
    required this.uuid,
    required this.title,
    required this.author,
  });
}
class Author {
  final String uuid;
  final String name;

  Author({
    required this.uuid,
    required this.name,
  });
}

我想知道能不能在Book的工厂方法里直接获取关联的Author数据?我试了下面的写法,但没法等待异步响应:

factory Book.fromJson(Map<String, dynamic> json) {
    return Book(
      uuid: json['uuid'],
      title: json['title'],
      author: fetchAuthor(json['author']),
    );
}

其中fetchAuthor方法定义如下:

Future<Author> fetchAuthor(authorUuid) async {
  http.Response author = await http.get(
    Uri.parse(apiURLAuthors + authorUuid),
  );
  if (author.statusCode == 200) {
    return Author.fromJson(jsonDecode(utf8.decode(author.bodyBytes)));
  } else {
    throw Exception("Failed to load author $authorUuid");
  }
}
解决方案

Dart的工厂方法不能是异步的,所以没法直接在Book.fromJson里等待fetchAuthor的异步结果。这里提供两种可行的解决思路:

1. 改用异步静态方法

放弃factory关键字,定义一个返回Future<Book>的静态方法,在内部等待作者数据加载完成后再创建Book实例:

static Future<Book> fromJsonAsync(Map<String, dynamic> json) async {
  final Author author = await fetchAuthor(json['author']);
  return Book(
    uuid: json['uuid'],
    title: json['title'],
    author: author,
  );
}

使用时需要通过await获取结果:

final Book book = await Book.fromJsonAsync(bookJsonData);

2. 先创建Book实例,后续异步加载作者信息

如果需要先展示书籍的基础信息,再延迟加载作者数据,可以修改Book类,让author字段变为可空,后续通过单独的方法加载:
首先调整Book类的定义:

class Book {
  final String uuid;
  final String title;
  final String authorUuid;
  Author? author;

  Book({
    required this.uuid,
    required this.title,
    required this.authorUuid,
    this.author,
  });

  factory Book.fromJson(Map<String, dynamic> json) {
    return Book(
      uuid: json['uuid'],
      title: json['title'],
      authorUuid: json['author'],
    );
  }

  Future<void> loadAuthor() async {
    author = await fetchAuthor(authorUuid);
  }
}

使用时可以先创建Book实例,再调用loadAuthor()加载作者信息:

final Book book = Book.fromJson(bookJsonData);
await book.loadAuthor();
// 此时book.author已赋值

额外优化建议

如果后端API支持,建议在请求书籍数据时直接嵌入作者的完整信息,这样可以避免额外的网络请求,提升效率。比如让后端返回的书籍JSON结构如下:

{
"uuid": "c6514be0-cced-43b7-b1f4-e66256c1dcaf",
"title": "Harry Potter",
"author": {
  "uuid": "6637e87b-c2ce-4774-b812-4e8a09312a40",
  "name": "J.K. Rowling"
}
}

这样就能直接在原有的Book.fromJson工厂方法里解析Author数据,无需异步操作:

factory Book.fromJson(Map<String, dynamic> json) {
  return Book(
    uuid: json['uuid'],
    title: json['title'],
    author: Author.fromJson(json['author']),
  );
}

内容的提问来源于stack exchange,提问作者Wag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:06:23