Flutter 給列表增加下拉刷新和上滑加載更多功能
有狀態(tài)組件
當(dāng) Flutter 的頁面需要?jiǎng)討B(tài)更新數(shù)據(jù)的時(shí)候,就會(huì)涉及到 UI 組件需要根據(jù)數(shù)據(jù)變化更新,此時(shí)也就意味著組件有了“狀態(tài)”。這就類似 React 的類組件和函數(shù)組件(只是后續(xù) React 使用了勾子函數(shù)實(shí)現(xiàn)了函數(shù)組件也可以有狀態(tài))。在 Flutter 中,組件也分為無狀態(tài)組件(StatelessWidget)和有狀態(tài)組件(StatefulWidget),一般盡量使用無狀態(tài)組件。但是如果組件本身需要維護(hù)自身狀態(tài)的時(shí)候,就需要使用有狀態(tài)組件了。有狀態(tài)組件的定義形式如下:
//有狀態(tài)組件聲明 class DynamicPage extends StatefulWidget { DynamicPage({Key key}) : super(key: key); //創(chuàng)建組件狀態(tài) @override _DynamicPageState createState() => _DynamicPageState(); } //組件狀態(tài) class _DynamicPageState extends State<DynamicPage> { @override Widget build(BuildContext context) { //UI 構(gòu)建 } }
有狀態(tài)組件實(shí)際的業(yè)務(wù)邏輯均由對應(yīng)的狀態(tài)實(shí)現(xiàn),包括數(shù)據(jù)定義和 UI 構(gòu)建。其核心在于有一個(gè) setState 方法用于通知界面刷新(這點(diǎn)也和 React 類似),一旦主動(dòng)調(diào)用了 setState 方法,界面就會(huì)進(jìn)行刷新。當(dāng)然,其中還有一些別的與狀態(tài)相關(guān)的方法,如狀態(tài)初始化方法 initialState。
異步 async/await
在網(wǎng)絡(luò)請求中,不可避免需要用到異步請求,這個(gè)時(shí)候就需要使用到 async 和 await。標(biāo)記為 async 的函數(shù)返回結(jié)果是一個(gè) Future 包裹的對象,調(diào)用方可以使用 await 從中獲取實(shí)際返回的數(shù)據(jù)。async/await 這個(gè)配對就完成了一個(gè)異步調(diào)用過程。在結(jié)果沒有返回的時(shí)候,主線程會(huì)執(zhí)行其他任務(wù)。在這里我們將列表數(shù)據(jù)獲取的方法改為 async 方式,以模擬網(wǎng)絡(luò)請求,如下所示:
static Future<List<Map<String, Object>>> list(int page, int size) async { return List<Map<String, Object>>.generate(size, (index) { return { 'title': '標(biāo)題${index + (page - 1) * size + 1}:這是一個(gè)列表標(biāo)題,最多兩行,多處部分將會(huì)被截取', 'imageUrl': 'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3331308357,177638268&fm=26&gp=0.jpg', 'viewCount': 180, }; }); }
調(diào)用的時(shí)候,使用 await即可獲取實(shí)際結(jié)果數(shù)據(jù),如下所示:
// _currentPage 為當(dāng)前頁碼,PAGE_SIZE為分頁大小 List<Map<String, Object>> _newItems = await DynamicMockData.list(_currentPage, PAGE_SIZE);
引入 flutter_easyrefresh
flutter 需要引入第三方插件時(shí),需要在 pubspec.yaml 文件下的dependencies節(jié)點(diǎn)下增加依賴,撰寫本文時(shí)flutter_easyrefresh的最新版為2.2.1,因此指定版本如下:
dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 flutter_easyrefresh: ^2.2.1
添加完依賴后,需要在項(xiàng)目目錄執(zhí)行 flutter pub get 命令更新依賴(VSCode 在檢測到 pubspec.yaml變化時(shí)會(huì)自動(dòng)拉取)。
使用 flutter_easyrefresh
對//www.dbjr.com.cn/article/213052.htm 上一篇的列表進(jìn)行改造分為如下三個(gè)步驟:
- 將頁面修改為有狀態(tài)組件,方便支持管理數(shù)據(jù)和根據(jù)數(shù)據(jù)更新界面
- 使用 EasyRefresh 包裹列表組件,并指定 onRefresh 和 onLoad 回調(diào)方法,以響應(yīng)下拉刷新和上滑加載更多的動(dòng)作。
- 根據(jù)當(dāng)前分頁獲取數(shù)據(jù),并更新到列表數(shù)據(jù)中,再調(diào)用 setState 更新狀態(tài)數(shù)據(jù)刷新界面。
整個(gè)新的 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'], ); }), ), ); } }
運(yùn)行結(jié)果
運(yùn)行結(jié)果如下圖所示,由于上拉加載過快沒法直接截圖看到。需要注意的是,首次加載的時(shí)候,EasyRefresh 并不會(huì)自動(dòng)加載,這個(gè)時(shí)候需要使用 EasyRefreshController 來控制,有興趣的同學(xué)可以參考 flutter_easyfresh 的文檔實(shí)現(xiàn)。
結(jié)語
flutter_easyrefresh 可以實(shí)現(xiàn)豐富的加載效果,包括自定義加載組件,乃至使用有趣的動(dòng)畫等等,基本上可以滿足各類下拉刷新或上滑加載更多的需要。建議可以參考文檔多嘗試其他效果,有興趣的也可以閱讀源碼看看具體的實(shí)現(xiàn)方式。
以上就是Flutter 給列表增加下拉刷新和上滑加載更多功能的詳細(xì)內(nèi)容,更多關(guān)于Flutter 下拉刷新和上滑加載的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android實(shí)現(xiàn)文字滾動(dòng)播放效果的代碼
這篇文章主要介紹了Android實(shí)現(xiàn)文字滾動(dòng)播放效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Android實(shí)現(xiàn)評論欄隨Recyclerview滑動(dòng)左右移動(dòng)
這篇文章主要介紹了Android實(shí)現(xiàn)評論欄隨Recyclerview滑動(dòng)左右移動(dòng)效果,仿約會(huì)吧應(yīng)用詳情頁實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2016-05-05Android XML設(shè)置屏幕方向(android:screenOrientation)詳解
這篇文章主要介紹了Android XML設(shè)置屏幕方向(android:screenOrientation)詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04Android studio 2020中的Android SDK 下載教程
這篇文章主要介紹了Android studio 2020中的Android SDK 下載教程,本文圖文并茂給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Thread、Handler和HandlerThread關(guān)系詳解
這篇文章主要介紹了Thread、Handler和HandlerThread關(guān)系詳解的相關(guān)資料,需要的朋友可以參考下2016-09-09