【效果图后续补上】缓存
结构是listview包含多种不一样类型的item,而后其中一个是SingleChildScrollView。
点击SingleChildScrollView中的item刷新listview中的部分数据。
可是发现当SingleChildScrollView滑动很远以后,再滑动listview,当SingleChildScrollView滑出屏幕以后,再滑回来SingleChildScrollView就回到了初始位子,这确定不行啊。
listview的item滑出屏幕以后会被回收的,设断点查看,来回滑动这个SingleChildScrollView并无从新建立,可是他里面的内容会被从新建立,这样每次从屏幕外面划回来SingleChildScrollView就回到初始状态了。markdown
接下来就是研究怎么不让它回收 重建,而后一顿查listview怎么缓存,SingleChildScrollView怎么保存滑动距离,保存状态等,查看源码发现SingleChildScrollView的controller默认是保存滑动距离的;可是由于SingleChildScrollView里面的内容都从新建立了因此滑动距离也就无用了;ide
无心中发现listview有 addAutomaticKeepAlives
这么一个属性,可是直接设置成 true又很差使,后来查了下发现它须要接收到须要保存状态的通知才会去保存item的,
查了下用法,在 StatefulWidget 的 state 中重写 wantKeepAlive,个人 SingleChildScrollView 里面的item正好都是 StatefulWidget;oop
最终参考 这个文章 修改了下 SingleChildScrollView 里面item的代码;ui
class TextWidget extends StatefulWidget {
final Key key;
final String text;
final bool selected;
// 接收一个Key
TextWidget(this.key, this.text, this.selected);
@override
State<StatefulWidget> createState() => TextWidgetState(this.text, this.selected);
}
class TextWidgetState extends State<TextWidget> with AutomaticKeepAliveClientMixin {
String _text = "0";
bool _selected = false;
TextWidgetState(this._text, this._selected);
@override
Widget build(BuildContext context) {
super.build(context);
return Text(
_text,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: _selected ? 18 : 16,
fontWeight: _selected ? FontWeight.bold : FontWeight.normal,
color: _selected ? color333 : color777),
);
}
void onPressed(bool selected) {
setState(() => _selected = selected);
}
@override
bool get wantKeepAlive => true;
}
复制代码
重要的是 with AutomaticKeepAliveClientMixin
和@override bool get wantKeepAlive => true;
this