IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Flutter 轻松构建加载更多(loading more),你花了多久弄明白架构设计 -> 正文阅读

[移动开发]Flutter 轻松构建加载更多(loading more),你花了多久弄明白架构设计

@override
void operator []=(int index, T value) {
// TODO: implement []=
_array[index] = value;
}

bool get hasMore => true;
bool isLoading = false;

IndicatorStatus indicatorStatus = IndicatorStatus.None;

Future loadMore() async {
if (isLoading || !hasMore) return true;
// TODO: implement loadMore

var preStatus = indicatorStatus;
indicatorStatus = this.length == 0
? IndicatorStatus.FullScreenBusying
: IndicatorStatus.LoadingMoreBusying;

if (preStatus == IndicatorStatus.Error) {
onStateChanged(this);
}
isLoading = true;
var isSuccess = await loadData();
isLoading = false;
if (isSuccess) {
if (this.length == 0) indicatorStatus = IndicatorStatus.Empty;
} else {
indicatorStatus = IndicatorStatus.Error;
}
onStateChanged(this);
return isSuccess;
}

Future loadData() async {
return true;
}

@override
Future onRefresh() async {
// TODO: implement OnRefresh
}

@override
int get length => _array.length;
set length(int newLength) => _array.length = newLength;

@override
void onStateChanged(LoadingMoreBase source) {
// TODO: implement notice
super.onStateChanged(source);
}
}

class _LoadingMoreBloc {
final _rebuild = new StreamController<LoadingMoreBase>.broadcast();
Stream<LoadingMoreBase> get rebuild => _rebuild.stream;

void onStateChanged(LoadingMoreBase source) {
if (!_rebuild?.isClosed) _rebuild.sink.add(source);
}

void dispose() {
_rebuild?.close();
}
}

继承于ListBase 方便后面继承

3个重要的方法: 用于加载更多

Future loadMore() async

用于刷新(重置列表)

Future onRefresh() async

用于获取数据,loadmore会调用这个方法,一般我们override的这个方法,loadmore里面有一些状态控制,如果你需要overrdie loadmore方法,注意查看下之前里面的状态控制代码

Future loadData() async

3个重要的属性: hasMore 判断是否还有更多 isLoading 判断是否正在获取数据 indicatorStatus 判断当前列表的状态

_LoadingMoreBloc 可以通过这个类来通知streambuilder更新UI

下面是如何继承使用这个base 类

class TuChongRepository extends LoadingMoreBase {
int pageindex = 1;

@override
// TODO: implement hasMore
bool _hasMore = true;
bool get hasMore => _hasMore && length < 20;

@override
Future onRefresh() async {
// TODO: implement onRefresh
pageindex = 1;
return loadMore();
}

@override
Future loadData() async {
// TODO: implement getData
String url = “”;
if (this.length == 0) {
url = “https://api.tuchong.com/feed-app”;
} else {
int lastPostId = this[this.length - 1].post_id;
url =
“https://api.tuchong.com/feed-app?post_id=KaTeX parse error: Expected 'EOF', got '&' at position 13: {lastPostId}&?page={pageindex}&type=loadmore”;
}
bool isSuccess = false;
try {
//to show loading more clearly, in your app,remove this
await Future.delayed(Duration(milliseconds: 500, seconds: 1));

var result = await HttpFactory.getInstance().getHttpClient().get(url);

var source = TuChongSource.fromJson(json.decode(result.body));
if (pageindex == 1) {
this.clear();
}

source.feedList.forEach((item) {
if (item.hasImage && !this.contains(item) && hasMore) {
this.add(item);
}
});

_hasMore = source.feedList.length != 0;
pageindex++;
isSuccess = true;
} catch (exception) {
isSuccess = false;
print(exception);
}
return isSuccess;
}
}

将你请求列表的代码加到getData方法里面,这样数据源的准备就好了。

下面说说UI组件 这一部分分为ListView/GridView 和SliverList/SliverGrid

ListView/GridView

LoadingMoreList 里面的部分代码,StreamBuilder为更新UI,NotificationListener为了监听滑动状态

class LoadingMoreList extends StatelessWidget {
final ListConfig listConfig;

LoadingMoreList(this.listConfig,{Key key})
super(key: key);
@override
Widget build(BuildContext context) {
return StreamBuilder(
builder: (d, s) {
return NotificationListener(
//key: _key,
onNotification: _handleScrollNotification,
child: NotificationListener(
onNotification: _handleGlowNotification,
child: listConfig.buildContent(context, s.data)),
);
},
stream: listConfig.sourceList?.rebuild,
);
}
}

ListConfig 里面提供了ListView/GridView的全部参数,这里我也提供了去掉滚动越界效果(就是列表滚不动的时候出现的水波纹效果)的2个属性showGlowLeading/showGlowTrailing。

final Axis scrollDirection;
final bool reverse;
final ScrollController controller;
final bool primary;
final ScrollPhysics physics;
final bool shrinkWrap;
final EdgeInsetsGeometry padding;
final double itemExtent;
final int itemCount;
final bool addAutomaticKeepAlives;
final bool addRepaintBoundaries;
final bool addSemanticIndexes;
final double cacheExtent;
final int semanticChildCount;

/// Whether to show the overscroll glow on the side with negative scroll
/// offsets.
final bool showGlowLeading;

/// Whether to show the overscroll glow on the side with positive scroll
/// offsets.
final bool showGlowTrailing;

ListConfig(
@required itemBuilder,
@required sourceList, {
this.showGlowLeading: true,
this.showGlowTrailing: true,
LoadingMoreIndicatorBuilder indicatorBuilder,
SliverGridDelegate gridDelegate,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.controller,
this.primary,
this.physics,
this.shrinkWrap = false,
this.padding,
this.itemExtent,
this.itemC

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

ount,
this.addAutomaticKeepAlives = true,
this.addRepaintBoundaries = true,
this.addSemanticIndexes = true,
this.cacheExtent,
this.semanticChildCount,
}) : super(itemBuilder, sourceList,
indicatorBuilder: indicatorBuilder, gridDelegate: gridDelegate);

sourceList 就是之前我们完成的loadingmore 数据源 itemBuilder 是每个item长什么样子

Demo code

class ListViewDemo extends StatefulWidget {
@override
_ListViewDemoState createState() => _ListViewDemoState();
}

class _ListViewDemoState extends State {
TuChongRepository listSourceRepository;
@override
void initState() {
// TODO: implement initState
listSourceRepository = new TuChongRepository();
super.initState();
}

@override
void dispose() {
listSourceRepository?.dispose();
// TODO: implement dispose
super.dispose();
}

@override
Widget build(BuildContext context) {
return Material(
child: Column(
children: [
AppBar(
title: Text(“ListViewDemo”),
),
Expanded(
child: LoadingMoreList(
ListConfig(
ItemBuilder.itemBuilder, listSourceRepository,
// showGlowLeading: false,
// showGlowTrailing: false,
padding: EdgeInsets.all(0.0)),),
)
],
),
);
}
}

这样子实现了一个加载更多的ListView,如果是GridView的话请给gridDelegate赋值.

SliverList/SliverGrid 支持多个loadmore列表 SliverListConfig 里面包含了SliverList/SliverGrid里面的参数

//config for SliverList and SliverGrid
class SliverListConfig extends LoadingMoreListConfig {
//whether show no more .
bool showNoMore = true;
//whether show fullscreenLoading for multiple sliver
bool showFullScreenLoading = true;

final bool addAutomaticKeepAlives;
final bool addRepaintBoundaries;
final bool addSemanticIndexes;
final SemanticIndexCallback semanticIndexCallback;
final int semanticIndexOffset;
final int childCount;

SliverListConfig(
@required itemBuilder,
@required sourceList, {
LoadingMoreIndicatorBuilder indicatorBuilder,
SliverGridDelegate gridDelegate,
this.addAutomaticKeepAlives = true,
this.addRepaintBoundaries = true,
this.addSemanticIndexes = true,
this.semanticIndexCallback = _kDefaultSemanticIndexCallback,
this.semanticIndexOffset = 0,
this.childCount,
}) : super(itemBuilder, sourceList,
indicatorBuilder: indicatorBuilder, gridDelegate: gridDelegate);

LoadingMoreCustomScrollView使用来创建Sliver组件,它包括了CustomScrollView的属性以及showGlowLeading/showGlowTrailing

//support for LoadingMoreSliverList
class LoadingMoreCustomScrollView extends StatefulWidget {
final List slivers;
final Axis scrollDirection;
final bool reverse;
final ScrollController controller;
final bool primary;
final ScrollPhysics physics;
final bool shrinkWrap;
final double cacheExtent;
final int semanticChildCount;

/// Whether to show the overscroll glow on the side with negative scroll
/// offsets.
final bool showGlowLeading;

/// Whether to show the overscroll glow on the side with positive scroll
/// offsets.
final bool showGlowTrailing;

LoadingMoreCustomScrollView({
Key key,
this.scrollDirection = Axis.vertical,
this.reverse = false,
this.controller,
this.primary,
this.physics,
this.shrinkWrap = false,
this.cacheExtent,
this.slivers = const [],
this.semanticChildCount,
this.showGlowLeading: true,
this.showGlowTrailing: true,
}) : assert(slivers != null),
super(key: key);

Demo code

简单的一个Sliver

class SliverListDemo extends StatefulWidget {
@override
_SliverListDemoState createState() => _SliverListDemoState();
}

class _SliverListDemoState extends State {
TuChongRepository listSourceRepository;
@override
void initState() {
// TODO: implement initState
listSourceRepository = new TuChongRepository();
super.initState();
}

@override
void dispose() {
listSourceRepository?.dispose();
// TODO: implement dispose
super.dispose();
}

@override
Widget build(BuildContext context) {

return Material(
child: LoadingMoreCustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text(“SliverListDemo”),
),
LoadingMoreSliverList(
SliverListConfig(
ItemBuilder.itemBuilder, listSourceRepository,
//isLastOne: false
))
],
),
);
}
}

多个Sliver

class MultipleSliverDemo extends StatefulWidget {
@override
_MultipleSliverDemoState createState() => _MultipleSliverDemoState();
}

class _MultipleSliverDemoState extends State {
TuChongRepository listSourceRepository;
TuChongRepository listSourceRepository1;

@override
void initState() {
// TODO: implement initState
listSourceRepository = new TuChongRepository();
listSourceRepository1 = new TuChongRepository();
super.initState();
}

@override
void dispose() {
listSourceRepository?.dispose();
listSourceRepository1?.dispose();

class _MultipleSliverDemoState extends State {
TuChongRepository listSourceRepository;
TuChongRepository listSourceRepository1;

@override
void initState() {
// TODO: implement initState
listSourceRepository = new TuChongRepository();
listSourceRepository1 = new TuChongRepository();
super.initState();
}

@override
void dispose() {
listSourceRepository?.dispose();
listSourceRepository1?.dispose();

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-05 12:09:21  更:2021-12-05 12:10:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:05:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码