Flutter 給列表增加下拉刷新和上滑加載更多功能
有狀態組件
當 Flutter 的頁面需要動態更新數據的時候,就會涉及到 UI 組件需要根據數據變化更新,此時也就意味著組件有瞭“狀態”。這就類似 React 的類組件和函數組件(隻是後續 React 使用瞭勾子函數實現瞭函數組件也可以有狀態)。在 Flutter 中,組件也分為無狀態組件(StatelessWidget)和有狀態組件(StatefulWidget),一般盡量使用無狀態組件。但是如果組件本身需要維護自身狀態的時候,就需要使用有狀態組件瞭。有狀態組件的定義形式如下:
//有狀態組件聲明 class DynamicPage extends StatefulWidget { DynamicPage({Key key}) : super(key: key); //創建組件狀態 @override _DynamicPageState createState() => _DynamicPageState(); } //組件狀態 class _DynamicPageState extends State<DynamicPage> { @override Widget build(BuildContext context) { //UI 構建 } }
有狀態組件實際的業務邏輯均由對應的狀態實現,包括數據定義和 UI 構建。其核心在於有一個 setState 方法用於通知界面刷新(這點也和 React 類似),一旦主動調用瞭 setState 方法,界面就會進行刷新。當然,其中還有一些別的與狀態相關的方法,如狀態初始化方法 initialState。
異步 async/await
在網絡請求中,不可避免需要用到異步請求,這個時候就需要使用到 async 和 await。標記為 async 的函數返回結果是一個 Future 包裹的對象,調用方可以使用 await 從中獲取實際返回的數據。async/await 這個配對就完成瞭一個異步調用過程。在結果沒有返回的時候,主線程會執行其他任務。在這裡我們將列表數據獲取的方法改為 async 方式,以模擬網絡請求,如下所示:
static Future<List<Map<String, Object>>> list(int page, int size) async { return List<Map<String, Object>>.generate(size, (index) { return { 'title': '標題${index + (page - 1) * size + 1}:這是一個列表標題,最多兩行,多處部分將會被截取', 'imageUrl': 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3331308357,177638268&fm=26&gp=0.jpg', 'viewCount': 180, }; }); }
調用的時候,使用 await即可獲取實際結果數據,如下所示:
// _currentPage 為當前頁碼,PAGE_SIZE為分頁大小 List<Map<String, Object>> _newItems = await DynamicMockData.list(_currentPage, PAGE_SIZE);
引入 flutter_easyrefresh
flutter 需要引入第三方插件時,需要在 pubspec.yaml 文件下的dependencies節點下增加依賴,撰寫本文時flutter_easyrefresh的最新版為2.2.1,因此指定版本如下:
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 flutter_easyrefresh: ^2.2.1
添加完依賴後,需要在項目目錄執行 flutter pub get 命令更新依賴(VSCode 在檢測到 pubspec.yaml變化時會自動拉取)。
使用 flutter_easyrefresh
對//www.jb51.net/article/213052.htm 上一篇的列表進行改造分為如下三個步驟:
- 將頁面修改為有狀態組件,方便支持管理數據和根據數據更新界面
- 使用 EasyRefresh 包裹列表組件,並指定 onRefresh 和 onLoad 回調方法,以響應下拉刷新和上滑加載更多的動作。
- 根據當前分頁獲取數據,並更新到列表數據中,再調用 setState 更新狀態數據刷新界面。
整個新的 dynamic_page 的代碼如下所示:
import 'package:flutter/material.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'dynamic_item.dart'; import 'dynamic_mock_data.dart'; class DynamicPage extends StatefulWidget { DynamicPage({Key key}) : super(key: key); @override _DynamicPageState createState() => _DynamicPageState(); } class _DynamicPageState extends State<DynamicPage> { List<Map<String, Object>> _listItems = []; int _currentPage = 1; static const int PAGE_SIZE = 20; void _refresh() async { _currentPage = 1; _requestNewItems(); } void _load() async { _currentPage += 1; _requestNewItems(); } void _requestNewItems() async { List<Map<String, Object>> _newItems = await DynamicMockData.list(_currentPage, PAGE_SIZE); this.setState(() { if (_currentPage > 1) { _listItems += _newItems; } else { _listItems = _newItems; } }); } @override Widget build(BuildContext context) { return Scaffold( body: EasyRefresh( onRefresh: () async { _refresh(); }, onLoad: () async { _load(); }, child: ListView.builder( itemCount: _listItems.length, itemBuilder: (context, index) { return DynamicItem( _listItems[index]['title'], _listItems[index]['imageUrl'], _listItems[index]['viewCount'], ); }), ), ); } }
運行結果
運行結果如下圖所示,由於上拉加載過快沒法直接截圖看到。需要註意的是,首次加載的時候,EasyRefresh 並不會自動加載,這個時候需要使用 EasyRefreshController 來控制,有興趣的同學可以參考 flutter_easyfresh 的文檔實現。
結語
flutter_easyrefresh 可以實現豐富的加載效果,包括自定義加載組件,乃至使用有趣的動畫等等,基本上可以滿足各類下拉刷新或上滑加載更多的需要。建議可以參考文檔多嘗試其他效果,有興趣的也可以閱讀源碼看看具體的實現方式。
以上就是Flutter 給列表增加下拉刷新和上滑加載更多功能的詳細內容,更多關於Flutter 下拉刷新和上滑加載的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 大型項目裡Flutter測試應用實例集成測試深度使用詳解
- Flutter路由fluro引入配置和使用的具體方法
- 為什麼不要在 Flutter 中使用全局變量
- Flutter 常用插件匯總
- Flutter listview如何實現下拉刷新上拉加載更多功能