Flutter分页加载列表插件loading_more_list的使用
Flutter分页加载列表插件loading_more_list的使用
简介
loading_more_list
是一个支持 ListView
, GridView
, WaterfallFlow
和 Slivers
的分页加载列表插件。它能帮助开发者更方便地实现列表的懒加载、错误处理和无更多数据提示等功能。
版本与信息
使用方法
1. 添加依赖
在项目的 pubspec.yaml
文件中添加 loading_more_list
依赖:
dependencies:
loading_more_list: any
2. 导入库
在 Dart 文件中导入 loading_more_list
库:
import 'package:loading_more_list/loading_more_list.dart';
3. 准备数据集合
创建一个继承自 LoadingMoreBase
的类来管理数据源:
class TuChongRepository extends LoadingMoreBase<TuChongItem> {
int pageindex = 1;
bool _hasMore = true;
bool forceRefresh = false;
@override
bool get hasMore => (_hasMore && length < 30) || forceRefresh;
@override
Future<bool> refresh([bool clearBeforeRequest = false]) async {
_hasMore = true;
pageindex = 1;
forceRefresh = !clearBeforeRequest;
var result = await super.refresh(clearBeforeRequest);
forceRefresh = false;
return result;
}
@override
Future<bool> loadData([bool isloadMoreAction = false]) async {
String url = "";
if (this.length == 0) {
url = "https://api.tuchong.com/feed-app";
} else {
int lastPostId = this[this.length - 1].postId;
url =
"https://api.tuchong.com/feed-app?post_id=$lastPostId&page=$pageindex&type=loadmore";
}
bool isSuccess = false;
try {
await Future.delayed(Duration(milliseconds: 500));
var result = await HttpClientHelper.get(url);
var source = TuChongSource.fromJson(json.decode(result.body));
if (pageindex == 1) {
this.clear();
}
for (var item in source.feedList) {
if (item.hasImage && !this.contains(item) && hasMore) this.add(item);
}
_hasMore = source.feedList.length != 0;
pageindex++;
isSuccess = true;
} catch (exception, stack) {
isSuccess = false;
print(exception);
print(stack);
}
return isSuccess;
}
}
4. 配置参数
ListConfig
类用于配置 LoadingMoreList
的参数,以下是常用参数:
参数名 | 描述 | 默认值 |
---|---|---|
itemBuilder |
列表项构建器 | 必填 |
sourceList |
数据源,必须继承自 LoadingMoreBase |
必填 |
showGlowLeading |
是否显示负滚动偏移量的过度滚动光晕 | 0.0 |
showGlowTrailing |
是否显示正滚动偏移量的过度滚动光晕 | - |
lastChildLayoutType |
最后一项的布局类型 | LastChildLayoutType.foot |
extendedListDelegate |
WaterfallFlow 或 ExtendedList 的代理 |
- |
gridDelegate |
GridView 的代理 |
- |
indicatorBuilder |
不同加载状态的 widget 构建器 | IndicatorWidget |
padding |
内边距 | - |
childCountBuilder |
子项数量构建器 | - |
5. 使用示例
ListView 示例
LoadingMoreList(
ListConfig<TuChongItem>(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
padding: EdgeInsets.all(0.0),
),
),
GridView 示例
LoadingMoreList(
ListConfig<TuChongItem>(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
padding: EdgeInsets.all(0.0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 3.0,
mainAxisSpacing: 3.0,
),
),
),
WaterfallFlow 示例
LoadingMoreList(
ListConfig<TuChongItem>(
extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
),
itemBuilder: _buildItem,
sourceList: listSourceRepository,
padding: EdgeInsets.all(5.0),
),
),
CustomScrollView 示例
LoadingMoreCustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text("MultipleSliverDemo"),
),
LoadingMoreSliverList(SliverListConfig<TuChongItem>(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
)),
SliverToBoxAdapter(
child: Container(
alignment: Alignment.center,
child: Text("Next list"),
color: Colors.blue,
height: 100.0,
),
),
LoadingMoreSliverList(
SliverListConfig<TuChongItem>(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository1,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 3.0,
mainAxisSpacing: 3.0,
),
),
),
SliverPersistentHeader(
delegate: CommonExtentSliverPersistentHeaderDelegate(
Container(
alignment: Alignment.center,
child: Text("Pinned Content"),
color: Colors.red,
),
100.0,
),
pinned: true,
),
LoadingMoreSliverList(
SliverListConfig<TuChongItem>(
itemBuilder: buildWaterfallFlowItem,
sourceList: listSourceRepository2,
padding: EdgeInsets.symmetric(horizontal: 5.0),
extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
),
),
),
],
),
6. 自定义加载指示器
通过 indicatorBuilder
参数可以自定义不同状态下的加载指示器:
enum IndicatorStatus {
None,
LoadingMoreBusying,
FullScreenBusying,
Error,
FullScreenError,
NoMoreLoad,
Empty
}
Widget _buildIndicator(BuildContext context, IndicatorStatus status) {
bool isSliver = false;
Widget widget;
switch (status) {
case IndicatorStatus.None:
widget = Container(height: 0.0);
break;
case IndicatorStatus.LoadingMoreBusying:
widget = Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(right: 5.0),
height: 15.0,
width: 15.0,
child: CircularProgressIndicator(),
),
Text("正在加载...不要着急")
],
);
break;
// 其他状态...
}
return widget;
}
LoadingMoreList(
ListConfig<TuChongItem>(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
indicatorBuilder: _buildIndicator,
padding: EdgeInsets.all(0.0),
),
),
7. 清理垃圾
通过 collectGarbage
回调可以在合适的时间清理资源(如图片缓存):
LoadingMoreList(
ListConfig<TuChongItem>(
extendedListDelegate: ExtendedListDelegate(
collectGarbage: (List<int> indexes) {
// 清理垃圾逻辑
},
),
),
),
8. 视口构建器
通过 viewportBuilder
可以跟踪进入视口的索引范围:
LoadingMoreList(
ListConfig<TuChongItem>(
extendedListDelegate: ExtendedListDelegate(
viewportBuilder: (int firstIndex, int lastIndex) {
print('viewport : [$firstIndex,$lastIndex]');
},
),
),
),
9. 最后一项布局类型
通过 lastChildLayoutType
可以设置最后一项的特殊布局:
enum LastChildLayoutType {
none,
fullCrossAxisExtent,
foot,
}
LoadingMoreList(
ListConfig<TuChongItem>(
lastChildLayoutType: LastChildLayoutType.foot,
),
),
10. 接近尾部
通过 closeToTrailing
参数可以让列表内容靠近尾部显示:
LoadingMoreList(
ListConfig<TuChongItem>(
extendedListDelegate: ExtendedListDelegate(
closeToTrailing: true,
),
),
),
完整示例代码
import 'package:flutter/material.dart';
import 'package:loading_more_list/loading_more_list.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Loading More List Example')),
body: MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final TuChongRepository listSourceRepository = TuChongRepository();
@override
void initState() {
super.initState();
listSourceRepository.initialData();
}
@override
Widget build(BuildContext context) {
return LoadingMoreList(
ListConfig<TuChongItem>(
itemBuilder: (BuildContext context, TuChongItem item, int index) {
return ListTile(
title: Text(item.title),
subtitle: Text(item.content),
);
},
sourceList: listSourceRepository,
padding: EdgeInsets.all(0.0),
indicatorBuilder: _buildIndicator,
),
);
}
Widget _buildIndicator(BuildContext context, IndicatorStatus status) {
bool isSliver = false;
Widget widget;
switch (status) {
case IndicatorStatus.None:
widget = Container(height: 0.0);
break;
case IndicatorStatus.LoadingMoreBusying:
widget = Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(right: 5.0),
height: 15.0,
width: 15.0,
child: CircularProgressIndicator(),
),
Text("正在加载...不要着急")
],
);
break;
case IndicatorStatus.Error:
widget = GestureDetector(
onTap: () {
listSourceRepository.errorRefresh();
},
child: Text("好像出现了问题呢?点击重试"),
);
break;
case IndicatorStatus.NoMoreLoad:
widget = Text("没有更多的了。。不要拖了");
break;
default:
widget = Container();
}
return widget;
}
}
以上是 loading_more_list
插件的详细使用说明和示例代码,希望对您有所帮助!
更多关于Flutter分页加载列表插件loading_more_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter分页加载列表插件loading_more_list的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用loading_more_list
插件来实现分页加载列表的示例代码。这个插件能够帮助你简化分页加载的实现过程。
首先,确保你的Flutter项目中已经包含了loading_more_list
插件。如果还没有添加,可以在pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
loading_more_list: ^x.y.z # 请将x.y.z替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来是一个完整的示例代码,展示了如何使用loading_more_list
插件来实现分页加载列表:
import 'package:flutter/material.dart';
import 'package:loading_more_list/loading_more_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Loading More List Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<String> dataSource = [];
bool hasMore = true;
int page = 1;
int pageSize = 10;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Loading More List Demo'),
),
body: LoadingMoreList<String>(
onLoadMore: _loadMoreData,
hasMore: hasMore,
itemCount: dataSource.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('Item ${dataSource[index]}'),
);
},
),
);
}
Future<void> _loadMoreData() async {
// 模拟网络请求
await Future.delayed(Duration(seconds: 2));
// 获取新数据
List<String> newData = [];
for (int i = 0; i < pageSize && hasMore; i++) {
int newIndex = (page - 1) * pageSize + i + 1;
newData.add("Data $newIndex");
// 假设数据总数是100,超过则没有更多数据
if (newIndex >= 100) {
hasMore = false;
}
}
// 更新状态
setState(() {
dataSource.addAll(newData);
page++;
});
}
}
代码解释
-
依赖添加:在
pubspec.yaml
中添加loading_more_list
插件依赖。 -
主应用:
MyApp
是一个简单的Material应用,包含了一个MyHomePage
页面。 -
状态管理:
MyHomePage
是一个有状态组件,用于管理数据加载的状态。 -
数据源和分页逻辑:
dataSource
:存储当前加载的数据。hasMore
:指示是否还有更多数据可以加载。page
和pageSize
:控制分页逻辑。
-
LoadingMoreList
:onLoadMore
:当需要加载更多数据时调用的函数。hasMore
:指示是否还有更多数据。itemCount
:当前数据源的长度。itemBuilder
:构建每个列表项的Widget。
-
数据加载:
_loadMoreData
函数模拟了一个异步的网络请求,延迟2秒后返回新数据。- 更新数据源和页码,并使用
setState
触发UI更新。
这个示例展示了如何使用loading_more_list
插件来简化分页加载列表的实现,同时保持了代码的清晰和可维护性。希望这个示例对你有所帮助!