【效果圖後續補上】緩存
結構是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