Flutter报错'type Null is not a subtype of ImageProvider',该排查何处?
我写了以下代码用于信息流展示帖子:
class Post { final String username; final String description; final ImageProvider profileImageUrl; Post({required this.username, required this.description, required this.profileImageUrl}); } List<Post> posts = [ Post(username: 'John Doe', description: 'Hello world!', profileImageUrl: Image.network('https://t3.ftcdn.net/jpg/05/16/27/58/360_F_516275801_f3Fsp17x6HQK0xQgDQEELoTuERO4SsWV.jpg').image), ];
之后用这段代码展示图片:
SizedBox( height: 50, width: 50, child: CircleAvatar( foregroundImage: posts[index].profileImageUrl, backgroundColor: Colors.transparent, ), ),
运行时报错:type 'Null' is not a subtype of type 'ImageProvider' of 'function result'
我改成这样后:
foregroundImage: posts[index].profileImageUrl ?? Image.network('https://t3.ftcdn.net/jpg/05/16/27/58/360_F_516275801_f3Fsp17x6HQK0xQgDQEELoTuERO4SsWV.jpg').image,
SDK又提示:
The left operand can't be null, so the right operand is never executed. Try removing the operator and the right operand.
我到底忽略了什么问题?
核心问题出在你用Image.network(...).image获取ImageProvider的方式上:
Image.network是一个Widget,它内部的image属性在Widget还没完成初始化时可能为null。你直接把这个可能为null的值传给Post的profileImageUrl(这个字段被声明为非空的ImageProvider),这就埋下了隐患——虽然写代码时没报错,但运行时这个值真的变成null了,就触发了类型转换错误。而Post类里的
profileImageUrl被标记为final ImageProvider(非空),所以SDK认为posts[index].profileImageUrl不可能为null,自然会提示??运算符是冗余的。
解决办法很简单:不要通过Image Widget的image属性获取ImageProvider,直接用NetworkImage类来创建ImageProvider:
修改Post列表的初始化代码:
List<Post> posts = [ Post( username: 'John Doe', description: 'Hello world!', profileImageUrl: NetworkImage('https://t3.ftcdn.net/jpg/05/16/27/58/360_F_516275801_f3Fsp17x6HQK0xQgDQEELoTuERO4SsWV.jpg'), ), ];
然后CircleAvatar的代码保持原来的写法即可:
foregroundImage: posts[index].profileImageUrl,
这样既保证了profileImageUrl从一开始就是合法的非空ImageProvider,运行时不会出现null错误,也不会有冗余的空值运算符提示。
内容的提问来源于stack exchange,提问作者PennyWise

