flutter - Flutter Provider:未处理的异常:查找已停用小部件的祖先是不安全的
问题描述
我是扑扑和飞镖的菜鸟。在尝试颤振提供者状态管理包时,我收到以下错误:
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.
E/flutter (23887): #11 _rootRun (dart:async/zone.dart:1184:13)
E/flutter (23887): #12 _CustomZone.run (dart:async/zone.dart:1077:19)
E/flutter (23887): #13 _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:1003:23)
E/flutter (23887): #14 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
E/flutter (23887): #15 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter (23887): #16 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter (23887): #17 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
我想做什么?
我想创建一个标签栏。选项卡项将从服务器动态获取。然后我将单击选项卡,它们将按类别 id 加载用户提要帖子。如果我在选项卡之间滑动,它不会引发任何错误。如果我一个一个地点击选项卡项目,它不会引发任何错误。但是如果我点击第二个下一个项目,它会抛出上面指定的错误。这是我的代码
FeedListScreen.dart:
import 'package:flutter/material.dart';
import 'package:flutter_x/Providers/FeedProvider.dart';
import 'package:flutter_x/Widgets/FeedList.dart';
import 'package:provider/provider.dart';
class FeedListScreen extends StatefulWidget {
@override
_FeedListScreenState createState() => _FeedListScreenState();
}
class _FeedListScreenState extends State<FeedListScreen> {
bool _canLoadTabs = false;
List<Tab> _tabs = [];
List<Widget> _tabContainers = [];
@override
void initState() {
Future.delayed(Duration(seconds: 0), () {
var fp = Provider.of<FeedProvider>(context, listen: false);
fp.fetchFeedTypes().then((value) {
for (int i = 0; i < fp.feedTypeList.length; i++) {
_tabs.add(Tab(text: fp.feedTypeList[i].name,));
_tabContainers.add(FeedList(fp.feedTypeList[i].id));
}
setState(() {
_canLoadTabs = true;
});
}
);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Consumer<FeedProvider>(
builder: (ctx, feedProvider, _) {
if (!_canLoadTabs) {
return Center(child: CircularProgressIndicator());
}
return DefaultTabController(
length: _tabs.length,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: _tabs,
isScrollable: true,
),
),
body: TabBarView(
children: _tabContainers,
),
)
);
},
);
}
}
FeedList.dart
import 'package:flutter/material.dart';
import 'package:flutter_x/Providers/FeedProvider.dart';
import 'package:provider/provider.dart';
class FeedList extends StatelessWidget {
String _id;
FeedList([String id]) {
_id = id;
}
@override
Widget build(BuildContext context) {
Future.delayed(Duration(seconds: 0), () {
if (_id == null) {
print('_id is null.. not fetching');
} else {
Provider.of<FeedProvider>(context, listen: false).fetchFeedList(page: 1, feedId: _id); //<= This line causing the error
}
});
return ListView.builder(
shrinkWrap: true,
itemCount: 20, //dummy
itemBuilder: (ctx, index) => ListTile(
leading: CircleAvatar(
child: Text('$index'),
),
),
);
}
}
FeedProvider.dart
import 'package:flutter/material.dart';
class FeedProvider with ChangeNotifier {
List<FeedType> _feedTypes = [];
List<FeedItem> _feedItemList = [];
///getters
List<FeedType> get feedTypeList => _feedTypes;
List<FeedItem> get feedList => _feedItemList;
.... other getters...
///setters
... other setters...
set feedTypeList(List<FeedType> ft) {
if (_feedTypes != ft) {
_feedTypes = ft;
notifyListeners();
}
}
set feedList(List<FeedItem> fl) {
if(fl.length == 0){
_feedItemList = [];
}else{
_feedItemList.addAll(fl);
}
notifyListeners();
}
///methods
Future<void> fetchFeedTypes() async {
feedTypeLoaderStatus = true;
error = '';
try {
var data = await _feedService.fetchFeedTypes(); //...http call
List<FeedType> rawFeedTypes = [];
for (int i = 0; i < data.length; i++) {
rawFeedTypes.add(FeedType.fromJson(data[i]));
}
feedTypeList = rawFeedTypes;
} catch (err) {
//...error handling codes
} finally {
feedTypeLoaderStatus = false;
}
}
Future<void> fetchFeedList({@required int page, String feedId}) async {
if(page == 1){
feedList = [];
}
try {
Map<String, dynamic> queryParams = {"page": page.toString()};
if(feedId != null){
queryParams["feed_type_id"] = feedId;
}
var data = await _feedService.fetchFeedList(queryParams); //...http calls
List<FeedItem> rawFeedList = [];
for (int i = 0; i < data.length; i++) {
rawFeedList.add(FeedItem.fromJson(data[i]));
}
feedList = rawFeedList;
} catch (err) {
feedList = [];
//.... error handling codes
} finally {
feedLoaderStatus = false;
}
}
}
无法弄清楚这里的错误。欢迎任何建议/代码改进
解决方案
推荐阅读
- codeigniter - PHP文件上传医学图像
- ios - 如何基于协议快速实现路由
- ios - 我的应用程序从“有一个或多个问题”变为“已完成处理”,而我没有碰它。是什么导致了这种变化?
- angular - Angular6 Accordion Permissions,即一旦完成填写所有表单字段,然后打开到下一个手风琴
- postgresql - 带有 UUID 主键的 SymmetricDS 和 Postgres 失败(uuid 类型的输入语法无效)
- python - 在python中反转字符串中的子字符串
- ms-access - 在同一位置链接后端密码保护的访问数据库
- node.js - Javascript从数组中分离值
- ruby-on-rails - 如何避免无效 url 请求攻击?
- javascript - PHP AJAX 混合匹配的结帐项目顺序