Flutter:异步任务在“initState()”中无法按预期工作
Posted
技术标签:
【中文标题】Flutter:异步任务在“initState()”中无法按预期工作【英文标题】:Flutter: Async task do not work as expected in "initState()" 【发布时间】:2019-08-29 07:15:57 【问题描述】:我正在尝试使用从 REST API 获得的数据在我的颤振应用程序中填充 DropDownMenu
。以下是我获取数据的方式。
class _CreateSellingAdvertisementState extends State<CreateSellingAdvertisement>
List<String> categoryList = List<String>();
List<String> productList = List<String>();
List<String> productUnitList = List<String>();
@override
void initState()
super.initState();
//Load category List
DataFetch()
.fetchCategoryList(
AppNavigation.getAPIUrl() +
"productCategory/getAllProductCategories",
ProductCategory)
.then((onValue)
List<String> listString = new List<String>();
for (int i = 0; i < onValue.length; i++)
listString.add(onValue[i].categoryName);
setState(()
categoryList = listString;
);
);
print(categoryList);
...........................
当我打印上面的categoryList
时,它始终是[]
。但是我使用FutureBuilder
使用了相同的方法,并且效果很好。
下面是DataFetch().fetchCategoryList
方法
Future<List<ProductCategory>> fetchCategoryList(
String url, Object obj) async
final response = await http.get(url);
// Use the compute function to run parsePhotos in a separate isolate
return parseCategoryDataList(response.body);
List<ProductCategory> parseCategoryDataList(String responseBody)
final parsed =
convert.json.decode(responseBody).cast<Map<String, dynamic>>();
List<ProductCategory> list = parsed
.map<ProductCategory>((json) => new ProductCategory.fromJson(json))
.toList();
return list;
下面是我的下拉列表代码
Widget _buildDropDown(List<String> list)
return new DropdownButton<String>(
items: list.map((String value)
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
).toList(),
value: "A",
isExpanded: true,
onChanged: (_) ,
);
下拉列表总是抛出以下异常
I/flutter (21217): The following assertion was thrown building CreateSellingAdvertisement(dirty, state:
I/flutter (21217): _CreateSellingAdvertisementState#1a80a):
I/flutter (21217): 'package:flutter/src/material/dropdown.dart': Failed assertion: line 560 pos 15: 'items == null ||
I/flutter (21217): items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value ==
I/flutter (21217): value).length == 1': is not true.
I/flutter (21217): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (21217): more information in this error message to help you determine and fix the underlying cause.
I/flutter (21217): In either case, please report this assertion by filing a bug on GitHub:
I/flutter (21217): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter (21217): When the exception was thrown, this was the stack:
I/flutter (21217): #2 new DropdownButton
I/flutter (21217): #3 _CreateSellingAdvertisementState._buildDropDown
I/flutter (21217): #4 _CreateSellingAdvertisementState.build
I/flutter (21217): #5 StatefulElement.build
I/flutter (21217): #6 ComponentElement.performRebuild
I/flutter (21217): #7 Element.rebuild
I/flutter (21217): #8 BuildOwner.buildScope
I/flutter (21217): #9 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame
I/flutter (21217): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback
I/flutter (21217): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback
I/flutter (21217): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame
I/flutter (21217): #13 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame
I/flutter (21217): #17 _invoke (dart:ui/hooks.dart:209:10)
I/flutter (21217): #18 _drawFrame (dart:ui/hooks.dart:168:3)
I/flutter (21217): (elided 5 frames from class _AssertionError and package dart:async)
这是为什么?
【问题讨论】:
你能不能尝试在setState
之后在.then
中打印categoryList 并检查
【参考方案1】:
Future
方法在initState
内部有效,这里的问题似乎是由于列表未按预期更新所致。将项目添加到 List 时,for 循环最好放在 setState()
内,最好将项目直接添加到 categoryList
。
setState(()
for (int i = 0; i < onValue.length; i++)
categoryList.add(onValue[i].categoryName);
);
在 for 循环中调用 setState()
也应该类似地工作。
for (int i = 0; i < onValue.length; i++)
setState(()
categoryList.add(onValue[i].categoryName);
【讨论】:
以上是关于Flutter:异步任务在“initState()”中无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
如何测试 initState() 中有异步调用的 Flutter 应用程序?