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
相关产品推荐
相关产品推荐

