天天看點

跨平台APP開發Flutter ListView 局部重新整理資料、ListView點贊收藏

題記

—— 執劍天涯,從你的點滴積累開始,所及之處,必精益求精。

Flutter是谷歌推出的最新的移動開發架構。

【x1】微信公衆号的每日提醒 随時随記 每日積累 随心而過 【x2】各種系列的視訊教程 免費開源 關注 你不會迷路 【x3】系列文章 百萬 Demo 随時 複制粘貼 使用

本文章實作的是 ListView 中 Item 局部資料重新整理的效果,如下圖所示。
跨平台APP開發Flutter ListView 局部重新整理資料、ListView點贊收藏

在這隻是一個 Demo ,是一個實作思路,在應用開發的更多場景中如 資訊清單的點贊、收藏等等,諸多業務場景都可使用。

1 Demo 實作

首先是這裡使用清單使用到的資料模型定義如下:

完整源碼
///ListView 測試資料 Model
class TestBean {
  String name;
  bool isCollect;

  TestBean({this.name, this.isCollect});
}           

然後就是 ListView 實作的首頁面,定義如下:

///ListView 局部資料更新使用 Demo
class TestListPartPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _TestABPageState();
  }
}

class _TestABPageState extends State {
  ///測試資料集合
  List<TestBean> _testList = [];

  @override
  void initState() {
    super.initState();
    ///模拟測試資料
    for (int i = 0; i < 100; i++) {
      _testList.add(TestBean(name: "測試資料 $i", isCollect: false));
    }
  }

  @override
  Widget build(BuildContext context) {
    ///頁面主體腳手架
    return Scaffold(
      appBar: AppBar(
        title: Text("ListView 局部資料更新 "),
      ),
      body: buildListView(),
    );
  }

  ///建構一個清單 ListView
  buildListView() {
    ///懶加載模式建構
    return ListView.builder(
      ///子Item的建構器
      itemBuilder: (BuildContext context, int index) {
        ///每個子Item的布局
       ///在這裡是封裝到了獨立的 StatefulWidget
        return TestListItemWidget(
          ///子Item對應的資料
          bean: _testList[index],
          ///可選參數 子Item辨別
          key: GlobalObjectKey(index),
        );
      },
      ///ListView子Item的個數
      itemCount: _testList.length,
    );
  }
}           

每個子 Item 的UI布局及功能封裝成了一個 獨立的 StatefulWidget,代碼如下:

///ListView 的子Item
class TestListItemWidget extends StatefulWidget {
  ///本Item對應的資料模型
  final TestBean bean;

  TestListItemWidget({@required this.bean, Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _ListItemState();
  }
}           
class _ListItemState extends State<TestListItemWidget> {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: Container(
        color: Colors.grey[300],
        padding: EdgeInsets.only(
          top: 5,
          bottom: 5,
        ),
        child: Container(
          padding: EdgeInsets.only(
            left: 15,
            right: 15,
          ),
          color: Colors.white,
          height: 60,
          child: buildRow(),
        ),
      ),
    );
  }

  ///内容區域
  Row buildRow() {
    ///左右線性排開
    return Row(
      children: [
        ///權重布局 文本占用空白區域
        Expanded(
            child: Text(
          "${widget.bean.name}",
        )),
        ///收藏按鈕
        RaisedButton(
          ///按鈕的背景
          color: widget.bean.isCollect ? Colors.blue : Colors.grey[200],
          ///點選更新目前 Item 資料以及重新整理頁面顯示
          onPressed: () {
            setState(() {
              widget.bean.isCollect = !widget.bean.isCollect;
            });
          },
          child: Text(
            "${widget.bean.isCollect ? '已收藏' : '收藏'}",
            style: TextStyle(
                color: widget.bean.isCollect ? Colors.white : Colors.red),
          ),
        ),
      ],
    );
  }
}           

2 原理分析

很多個為什麼,咱們一一來分析,大家如果有疑問或者不同的看法,可以回複評論,一起優化

2.1 實作的真的是局部重新整理嗎 ?

答案為 是的,在這裡模拟了100條資料,但是這裡使用的是懶加載模式建構的,是以實際繪制出來的 Item 并不是 100 條,如下圖所示:

跨平台APP開發Flutter ListView 局部重新整理資料、ListView點贊收藏

滑動時,滑出螢幕外的,超出ListView緩存區域的就會被銷毀,在本 Demo 本測試模拟器中,ListView中始終是繪制的 16 個子 Item。

ListView 每一個子 Item 都是一個獨立的 StatefulWidget ,都對應的是一個 獨立的 State ,是以調用 setState方法來重新整理隻是重新整理了目前的 StatefulWidget 内容區域,當然從源碼角度也有另外的解讀,這裡不去說源碼。

當然在實際業務場景中,你的 ListView 中的 Item的UI布局功能可能足夠的複雜,不用擔心 ,你也可以采用這種思路 ,把每個 Item 中的 部分 Widget 再次封裝到不同的StatefulWidget 中,這樣也能實作ListView 中一個Item中不同的Widget 重新整理不同的區域。

當然 也可以在 ListView 的Item 中使用 Stream 、Provider 、BloC等等,小編這裡也有說明

點選檢視
2.2 狀态如何儲存的 ???

通過資料模型來儲存的狀态,因為在這裡使用的是根據 TestBean 中 isCollect 的值來建構不同的樣式的,List中儲存的 TestBean 的辨別不同,建構的子Item的樣式不同。

2.3 List 中的資料是如何更新的 ???

還是這一句更新的:

setState(() {
     widget.bean.isCollect = !widget.bean.isCollect;
   });           

效果同下

///修改資料
   widget.bean.isCollect = !widget.bean.isCollect;
   ///重新整理頁面顯示
   setState(() {  });           

在這一步修改資料,看下圖你就明白了

跨平台APP開發Flutter ListView 局部重新整理資料、ListView點贊收藏

ListView 的子Item 中(TestListItemWidget)使用的資料模型在記憶體區域中還是在 TestListPartPage 這裡建立的 _testList 集合中儲存的對象實體,整個過程中隻是通過指針索引來綁定資料,修改資料實際上修改的還是同一塊記憶體區域中的資料。

完畢

以小編的性格,要實作百萬Demo随時複制粘貼肯定是需要源碼的

github 完整源碼 點選檢視

當然以小編的性格,肯定是要有視訊錄制的,目前正在錄制中,你可以關注一下

西瓜視訊 --- 早起的年輕人

随後會上傳

繼續閱讀