数据更新后颤振列表视图不更新
Posted
技术标签:
【中文标题】数据更新后颤振列表视图不更新【英文标题】:Flutter listview not updating after data update 【发布时间】:2020-06-03 21:19:13 【问题描述】:我在 bottomSheet 中有一个 ListView,它是使用元素数组构建的。目前我在那里有一个“空”项目,然后是.clear()
ed,并在异步数据库调用后填充。
变量更新是正确的,我尝试使用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();
【问题讨论】:
【参考方案1】:在我看来,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]),
);
【讨论】:
感谢它实际上对我有用。 UniqueKey 使它工作。唯一的区别是我没有使用 setState 而是将数据推送到流 为我工作。没有它 setState 什么也没做。 setState 有时不适用于inheritedWidget。添加 UniqueKey() 成功了。谢谢;) 这应该是公认的答案。像魅力一样工作。 这个答案是救命稻草【参考方案2】:您的ListView
仅在您的FloatingActionButton
上调用onPressed
时构建。
我认为这就是为什么当状态发生变化时它不会再次构建的原因。
您可以包装代码以在具有自己状态的新 StatefulWidget
中构建 ListView
,然后在 testList
更改时更新它。
【讨论】:
所以,第二个dart
文件,extends StatefulWidget
,然后是 CreateState,新类扩展 State,然后有 Widget build(BC ctx) return BottomSheet( builder: ....
?
是的,应该可以!您可以添加一个名为 updateList(List<String> list)
的方法并持有对小部件的引用以更新它
嗯,似乎无法正常工作。我已经更新了问题以上是关于数据更新后颤振列表视图不更新的主要内容,如果未能解决你的问题,请参考以下文章