Flutter报错type 'Null' is not a subtype of type 'RenderBox'如何解决?
错误原因
- 调用时机错误:在
_SmallState构造函数中直接执行坐标获取逻辑时,组件尚未执行build流程,所有绑定了GlobalKey的GridView子元素还未挂载到渲染树,key.currentContext返回null,强制转换为RenderBox类型就会触发空类型转换异常。即使将调用逻辑移到initState中也会出现相同问题,因为initState执行阶段组件仍未完成渲染挂载。 - 列表赋值逻辑错误:初始化
positions为空列表后直接通过下标positions[i]赋值,会触发数组下标越界异常,空列表不存在对应索引的存储位置。 - 类型转换缺少校验:直接使用
as RenderBox强制转换没有做前置空校验和类型校验,即使渲染完成,也存在返回非RenderBox类型渲染对象的可能,会触发转换异常。
修复步骤
- 移除State构造函数中的
initOffsetsPositions调用,改为监听首帧渲染完成回调后再执行坐标获取逻辑,Flutter提供的addPostFrameCallback回调会在组件第一帧渲染完成、所有元素已挂载到渲染树后触发。 - 修改
positions列表的赋值逻辑,改用add方法追加元素,避免下标越界。 - 给RenderBox的获取逻辑增加空校验和类型校验,避免强制转换异常。
修复后代码
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class Small extends StatefulWidget { Small({Key? key}) : super(key: key); @override _SmallState createState() => _SmallState(); } class _SmallState extends State<Small> { late Keys keys; late List<Offset> positions; _SmallState() { keys = Keys(); positions = []; } List<String> images = [ 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://simg.nicepng.com/png/small/107-1076994_white-square-outline-plain-black-background-square.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png', 'https://static.javatpoint.com/tutorial/flutter/images/flutter-logo.png' ]; void initOffsetsPositions() { List<GlobalKey> keyList = keys.getListOfKeys(); print(keyList); positions.clear(); for (int i = 0; i < keyList.length; i++) { final offset = getOffsetsPositions(keyList[i]); if (offset != null) { positions.add(offset); print(positions[i]); } } } Offset? getOffsetsPositions(GlobalKey key) { final renderObject = key.currentContext?.findRenderObject(); if (renderObject is RenderBox) { Offset position = renderObject.globalToLocal(Offset.zero); Size size = renderObject.size; print('Size: ${size.width}, ${size.height}'); return position; } return null; } @override Widget build(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { initOffsetsPositions(); }); return Center( child: Container( padding: const EdgeInsets.all(12.0), child: GridView.builder( itemCount: images.length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 4.0, mainAxisSpacing: 4.0), itemBuilder: (BuildContext context, int index) { return Stack( children: [ Positioned( child: Container( key: keys.getKeyOfList(index), child: Image.network(images[index]), ), ), ], ); }, ), ), ); } } class Keys { static final key0 = GlobalKey(); static final key1 = GlobalKey(); static final key2 = GlobalKey(); static final key3 = GlobalKey(); static final key4 = GlobalKey(); static final key5 = GlobalKey(); static final key6 = GlobalKey(); static final key7 = GlobalKey(); static final key8 = GlobalKey(); final List<GlobalKey> keyList = [ key0, key1, key2, key3, key4, key5, key6, key7, key8, ]; GlobalKey getKeyOfList(index) { return keyList[index]; } List<GlobalKey> getListOfKeys() { return keyList; } }
内容的提问来源于stack exchange,提问作者Eduardo Tolentino
相关产品推荐
相关产品推荐

