我在bottomSheet中有一个ListView,它是使用元素数组构建的。目前,我在其中有一个“空”项目,然后在进行异步DB调用后.clear()
填充并填充了该项目。
变量更新正确,我尝试使用setState((){})
,但ListView根本没有更新。我需要关闭bottomSheet,重新打开它,然后ListView包含正确的项目。
我是否只需要调用setState
或是否需要标记bottomSheet构建器进行更新?
主要ListView部分:
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Map'),
backgroundColor: Colors.green[700],
),
//Put in a stack widget so can layer other widgets on top of map widget
body: Stack(
children: <Widget>[
GoogleMap(
mapType: _currentMapType,
markers: _markers,
onMapCreated: _onMapCreated,
onCameraMove: _onCameraMove,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
alignment: Alignment.bottomCenter,
child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
SizedBox(width: 16.0),
Builder(
builder: (context) => FloatingActionButton(
...
),
),
SizedBox(width: 16.0),
FloatingActionButton(
...
),
SizedBox(width: 16.0),
Builder(
builder: (context) => FloatingActionButton(
child: Icon(Icons.file_download, size: 36.0),
backgroundColor: Colors.green,
onPressed: () {
showBottomSheet(
context: context,
builder: (context) {
return ListView(
padding: EdgeInsets.all(15.0),
children: <Widget>[
...
Divider(),
ListTile(
title: Text("Remote JSON Download"),
trailing:
Icon(Icons.refresh),
selected: true,
onTap: _OnPressedReloadJSON, <-------------
),
Divider(),
Container(
height: 150.0,
child: ListView.builder( <-------------
scrollDirection: Axis.horizontal,
itemCount : testList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
padding: EdgeInsets.all(5.0),
margin: EdgeInsets.all(5.0),
width: 150.0,
color: Colors.red,
child: Text(testList[index]),
);
},
),
),
异步获取:
class _MyAppState extends State<MyApp> {
...
_OnPressedReloadJSON() {
fetchJSONAndMakeListTile();
}
...
List<String> testList= ["empty"];
Future<http.Response> fetchJSONAndMakeListTile() async {
final response = await http.get('https://..... file.json');
// If the server did return a 200 OK response, then parse the JSON.
if (response.statusCode == 200) {
List<db_manager.MyObject> myObjects = (json.decode(response.body) as List)
.map((e) => db_manager.MyObject.fromJson(e))
.toList();
testList.clear();
myObjects.forEach((db_manager.MyObject al) {
testList.add(al.code);
print("debug:"+al.code+" - "+al.name); <------------- prints correctly
});
//TODO Does this even work?
//Trigger update of state - ie redraw/reload UI elements
setState(() {});
} else {
// If the server did not return a 200 OK response, then throw an exception.
print(response);
throw Exception('Failed to load json');
}
}
更新:
我已经将BottomSheet构建器作为自己的StatefulWidget抽象到另一个类中(根据另一个答案),但是我似乎无法从主dart文件访问void onPress()
方法。如果BottomSheet创建/生成器位于此单独的dart文件中,如何调用它进行生成,然后使用async
调用来更新其状态,从而更新列表视图内容列表?
BottomSheetWidget.dart
class BottomSheetDatabases extends StatefulWidget {
@override
_BottomSheetDatabases createState() => _BottomSheetDatabases();
}
class _BottomSheetDatabases extends State<BottomSheetDatabases> {
void _onpress() {
}
void loadMe() {
}
List<String> testList= ["empty"];
@override
Widget build(BuildContext context) {
return BottomSheet(
builder: (context) {
return ListView(
padding: EdgeInsets.all(15.0),
children: <Widget>[
ListTile(
...
),
Divider(),
Container(
height: 150.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: testList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
key: UniqueKey(),
//TODO ??
padding: EdgeInsets.all(5.0),
margin: EdgeInsets.all(5.0),
width: 150.0,
color: Colors.red,
child: Text(testList[index]),
);
},
),
//),
//),
),
...
Main.dart :
void _loadSheetDatabases() {
BottomSheetWidget bottomSheetwidget = BottomSheetWidget();
bottomSheetwidget.loadMe();
}
答案 0 :(得分:9)
在我看来ListView.Builder返回的小部件中缺少Key
,请尝试在容器或文本中放入UniqueKey()
或ValueKey:
Container(
key: UniqueKey(),
padding: EdgeInsets.all(5.0),
margin: EdgeInsets.all(5.0),
width: 150.0,
color: Colors.red,
child: Text(testList[index]),
);
答案 1 :(得分:0)
只有在您的ListView
上调用onPressed
时,才会构建您的FloatingActionButton
。
我认为这就是为什么状态更改时不会再次构建它的原因。
您可以包装代码以将ListView
构建到具有自己状态的新StatefulWidget
中,然后在testList
更改时对其进行更新。