flutter ListView刷新
我怎么动态地更新 ListView?
在 iOS 中,你改变列表的数据,并通过 reloadData()
方法来通知 table 或是 collection view。
在 Flutter 中,如果你想通过 setState()
方法来更新 widget 列表,你会很快发现你的数据展示并没有变化。这是因为当 setState()
被调用时,Flutter 渲染引擎会去检查 widget 树来查看是否有什么地方被改变了。当它得到你的 ListView
时,它会使用一个 ==
判断,并且发现两个 ListView
是相同的。没有什么东西是变了的,因此更新不是必须的。
一个更新 ListView
的简单方法是,在 setState()
中创建一个新的 list,并把旧 list 的数据拷贝给新的 list。虽然这样很简单,但当数据集很大时,并不推荐这样做:
一个推荐的、高效的且有效的做法是,使用 ListView.Builder
来构建列表。这个方法在你想要构建动态列表,或是列表拥有大量数据时会非常好用。
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); } } class SampleAppPage extends StatefulWidget { SampleAppPage({Key key}) : super(key: key); @override _SampleAppPageState createState() => _SampleAppPageState(); } class _SampleAppPageState extends State<SampleAppPage> { List widgets = []; @override void initState() { super.initState(); for (int i = 0; i < 100; i++) { widgets.add(getRow(i)); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: ListView.builder( itemCount: widgets.length, itemBuilder: (BuildContext context, int position) { return getRow(position); }, ), ); } Widget getRow(int i) { return GestureDetector( child: Padding( padding: EdgeInsets.all(10.0), child: Text("Row $i"), ), onTap: () { setState(() { widgets.add(getRow(widgets.length + 1)); print('row $i'); }); }, ); } }
与创建一个 “ListView” 不同,创建一个 ListView.builder
接受两个主要参数:列表的初始长度,和一个 ItemBuilder
方法。
ItemBuilder
方法和 cellForItemAt
代理方法非常类似,它接受一个位置,并且返回在这个位置上你希望渲染的 cell。
最后,也是最重要的,注意 onTap()
函数里并没有重新创建一个 list,而是 .add
了一个 widget。