Flutter TabController无法获取API返回的视频列表长度如何解决
问题根源
_getAllVideos 是异步函数,initState 调用它时不会等待异步请求完成,会直接执行后续的 TabController 初始化逻辑,此时接口还未返回数据,_videoList 还是初始的空数组,因此拿到的长度为 0。
解决步骤
按以下方式修改代码即可正常获取长度:
- 初始化阶段先创建临时 TabController,等接口返回数据后再更新控制器
- 注意销毁旧控制器避免内存泄漏
- 增加加载状态判断避免渲染不匹配报错
1. 修改initState逻辑
late TabController _tabController; bool isLoading = true; List<Video> _videoList = []; @override void initState() { super.initState(); // 先初始化临时控制器,长度填0即可 _tabController = TabController(length: 0, vsync: this); _getAllVideos(); }
2. 修改_getAllVideos逻辑,拿到数据后更新TabController
_getAllVideos() async { var categories = await _videoService.getVideos(); var _list = json.decode(categories.body); List<Video> results = []; _list['data'].forEach((data) { var model = Video(); model.id = data["id"]; model.videoUrl = data["videourl"]; model.likes = data["likes"]; model.profileImg = data["profileImg"]; results.add(model); }); if(mounted){ // 先销毁旧的控制器 _tabController.dispose(); // 用最新的视频列表长度创建新控制器 _tabController = TabController(length: results.length, vsync: this); setState(() { _videoList = results; isLoading = false; }); print(_videoList.length); // 此时可拿到正确长度 } }
3. 给getBody增加加载状态判断,避免渲染报错
Widget getBody() { // 数据加载完成前显示加载动画 if (isLoading) { return const Center(child: CircularProgressIndicator()); } var size = MediaQuery.of(context).size; return RotatedBox( quarterTurns: 1, child: TabBarView( physics: const BouncingScrollPhysics(), controller: _tabController, children: List.generate(_videoList.length, (index) { return VideoPlayerItem( videoUrl: _videoList[index].videoUrl!.toString(), profileImg: _videoList[index].albumImg!, likes: _videoList[index].likes.toString(), ); },), ), ); }
4. 页面销毁时释放控制器
@override void dispose() { _tabController.dispose(); super.dispose(); }
注意:如果配套使用了TabBar组件,TabBar的子元素数量也要和_videoList长度保持一致,在setState更新数据后同步渲染即可
内容的提问来源于stack exchange,提问作者Pramod Yadav
相关产品推荐
相关产品推荐

