flutter刷新框架easyrefresh加载出现的bug
flutter_easyrefresh 加载多次问题修复flutter_easyrefresh是一个下拉刷新上拉加载的插件,具体我就不介绍了,这里主要是解决flutter_easyrefresh的bug,主要我在用此插件的时候遇到如下两个问题:①.上拉加载最后的footer不消失②.加载少量数据出现多次加载现象解决方案如下是问题及解决过程,如果想直接看最终解决方案请拉到最后面有最终版本第一个问题现
flutter_easyrefresh 加载多次问题修复
flutter_easyrefresh 是一个下拉刷新上拉加载的插件,具体我就不介绍了,这里主要是解决flutter_easyrefresh的bug,主要我在用此插件的时候遇到如下两个问题:
①.上拉加载最后的footer不消失
②.加载少量数据出现多次加载现象解决方案
如下是问题及解决过程,如果想直接看最终解决方案请拉到最后面有最终版本
第一个问题现象如下,就是加载过程中在数据不能占满整个界面的时候footer是不会自动消失的
解决方案:加载完成延时一秒将onLoad置为false即可,即footer不会继续显示。
在onLoad的地方添加isFooter用来控制footer是否显示
onLoad: _isFooter
? () async {
await Future.delayed(Duration(seconds: 0), () {
print('onLoad');
setState(() {
_count += 1;
});
_controller.finishLoad(noMore: _count >= 10);
loadingBottomControl();
});
}
: null,
下面的逻辑是加载完成一秒后让其不显示
void loadingBottomControl() {
Future.delayed(Duration(milliseconds: 1000), () {
setState(() {
_isFooter = false;
Future.delayed(Duration(milliseconds: 1000), () {
setState(() {
_isFooter = true;
});
});
});
});
}
最后别忘了添加变量
bool _isFooter = true;
以上代码即可解决第一个问题,但是当加载较少的数据时会出现多次加载现象,解决方案:
监听当前界面事件,让其在一次点击后只能刷新一次,注意此处不能用GestureDetector,因为GestureDetector只能监听纯单击,不能监听滑动的点击,此处我们用的是Listener,解决方案如下:
bool _isLoad = false;//防止load多次加载
Listener(
onPointerDown: (p) {
setState(() {
_isLoad = true;//设置成true,可以加载
print("onPointerDown$_isLoad");
});
},
child: EasyRefresh.custom(
enableControlFinishRefresh: false,
enableControlFinishLoad: true,
controller: _controller,
header: ClassicalHeader(),
footer: ClassicalFooter(),
onRefresh: () async {
await Future.delayed(Duration(seconds: 0), () {
print('onRefresh');
setState(() {
_count = 1;
});
_controller.resetLoadState();
});
},
onLoad: _isFooter
? () async {
await Future.delayed(Duration(seconds: 0), () {
print('onLoad');
print("onLoad$_isLoad");
if (_isLoad) {
_isLoad = false;//设置成false,防止多次加载
setState(() {
_count += 1;
});
_controller.finishLoad(noMore: _count >= 10);
loadingBottomControl();
} else {
_controller.finishLoad();
}
});
}
: null,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
width: 60.0,
height: 60.0,
child: Center(
child: Text('$index'),
),
color: index % 2 == 0
? Colors.grey[300]
: Colors.transparent,
);
},
childCount: _count,
),
),
],
),
)
如上可以解决多次加载问题,但是会出现上拉不放底部加载完成闪烁问题,解决方案如下:
Listener(
onPointerDown: (p) {
setState(() {
_isLoad = true;
_isFooter = true;//在点击过后才让其显示
print("onPointerDown$_isLoad");
});
},
child: EasyRefresh.custom(
enableControlFinishRefresh: false,
enableControlFinishLoad: true,
controller: _controller,
header: ClassicalHeader(),
footer: ClassicalFooter(),
onRefresh: () async {
await Future.delayed(Duration(seconds: 0), () {
print('onRefresh');
setState(() {
_count = 1;
});
_controller.resetLoadState();
});
},
onLoad: _isFooter
? () async {
await Future.delayed(Duration(seconds: 0), () {
print('onLoad');
print("onLoad$_isLoad");
if (_isLoad) {
_isLoad = false;
setState(() {
_count += 1;
});
_controller.finishLoad(noMore: _count >= 10);
loadingBottomControl();
} else {
_controller.finishLoad();
}
});
}
: null,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
width: 60.0,
height: 60.0,
child: Center(
child: Text('$index'),
),
color: index % 2 == 0
? Colors.grey[300]
: Colors.transparent,
);
},
childCount: _count,
),
),
],
),
));
//此处修改为不显示isFooter
void loadingBottomControl() {
Future.delayed(Duration(milliseconds: 1000), () {
setState(() {
_isFooter = false;
});
});
}
由于上述代码在一秒后就隐藏footer,感觉效果不好,作如下修改:
bool _isFooter = true;//控制footer是否显示
bool _isLoad = false;//防止load多次加载
bool _isMove = false;//防止load多次加载
bool _isAutoClose = false;//是否是一秒后自动关闭footer
Listener(
onPointerDown: (p) {
setState(() {
_isLoad = true;
_isFooter = true;
print("onPointerDown$_isLoad");
});
},
onPointerMove: (p){
setState(() {
_isMove = true;
});
},
onPointerUp: (p){
_isMove = false;
if(!_isAutoClose) {
setState(() {
_isAutoClose = true;
_isFooter = false;
});
}
},
child: EasyRefresh.custom(
enableControlFinishRefresh: false,
enableControlFinishLoad: true,
controller: _controller,
header: ClassicalHeader(),
footer: ClassicalFooter(),
onRefresh: () async {
await Future.delayed(Duration(seconds: 0), () {
print('onRefresh');
setState(() {
_count = 1;
});
_controller.resetLoadState();
});
},
onLoad: _isFooter
? () async {
await Future.delayed(Duration(seconds: 0), () {
print('onLoad');
print("onLoad$_isLoad");
if (_isLoad) {
_isLoad = false;
setState(() {
_count += 1;
});
_controller.finishLoad(noMore: _count >= 10);
loadingBottomControl();
} else {
_controller.finishLoad();
}
});
}
: null,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
width: 60.0,
height: 60.0,
child: Center(
child: Text('$index'),
),
color: index % 2 == 0
? Colors.grey[300]
: Colors.transparent,
);
},
childCount: _count,
),
),
],
),
)
void loadingBottomControl() {
Future.delayed(Duration(milliseconds: 1000), () {
setState(() {
if(_isMove) {
_isAutoClose = false;
} else {
_isAutoClose = true;
_isFooter = false;
}
});
});
}
最后附上全部代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
// App名字
title: 'EasyRefresh',
// App主题
theme: new ThemeData(
primarySwatch: Colors.orange,
),
// 主页
home: _Example(),
localizationsDelegates: [
GlobalEasyRefreshLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
);
}
}
class _Example extends StatefulWidget {
@override
_ExampleState createState() {
return _ExampleState();
}
}
class _ExampleState extends State<_Example> {
EasyRefreshController _controller;
// 条目总数
int _count = 1;
bool _isFooter = true;//控制footer是否显示
bool _isLoad = false;//防止load多次加载
bool _isMove = false;//防止load多次加载
bool _isAutoClose = false;//是否是一秒后自动关闭footer
@override
void initState() {
super.initState();
_controller = EasyRefreshController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EasyRefresh"),
),
body: Listener(
onPointerDown: (p) {
setState(() {
_isLoad = true;
_isFooter = true;
print("onPointerDown$_isLoad");
});
},
onPointerMove: (p){
setState(() {
_isMove = true;
});
},
onPointerUp: (p){
_isMove = false;
if(!_isAutoClose) {
setState(() {
_isAutoClose = true;
_isFooter = false;
});
}
},
child: EasyRefresh.custom(
enableControlFinishRefresh: false,
enableControlFinishLoad: true,
controller: _controller,
header: ClassicalHeader(),
footer: ClassicalFooter(),
onRefresh: () async {
await Future.delayed(Duration(seconds: 0), () {
print('onRefresh');
setState(() {
_count = 1;
});
_controller.resetLoadState();
});
},
onLoad: _isFooter
? () async {
await Future.delayed(Duration(seconds: 0), () {
print('onLoad');
print("onLoad$_isLoad");
if (_isLoad) {
_isLoad = false;
setState(() {
_count += 1;
});
_controller.finishLoad(noMore: _count >= 10);
loadingBottomControl();
} else {
_controller.finishLoad();
}
});
}
: null,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
width: 60.0,
height: 60.0,
child: Center(
child: Text('$index'),
),
color: index % 2 == 0
? Colors.grey[300]
: Colors.transparent,
);
},
childCount: _count,
),
),
],
),
));
}
void loadingBottomControl() {
Future.delayed(Duration(milliseconds: 1000), () {
setState(() {
if(_isMove) {
_isAutoClose = false;
} else {
_isAutoClose = true;
_isFooter = false;
}
});
});
}
}
上面的代码是嵌套到界面内部的,下面是直接包装到EasyRefresh中,直接调用即可:
以下是最终版本!!!其中用到了高级函数和扩展函数特性,需要flutter dev分支或者flutter master分支并且dart版本是2.6以上,以后可能会放到flutter stable分支中,当下测试还是不能使用在stable分支和beta分支中,如果不想用master或者dev版本只能用上面的方案了!
import 'package:flutter/widgets.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
//此处是将包装方法封装到EasyRefresh 中
extension SmartRefresh on EasyRefresh {
static bool _isFooter = true; //控制footer是否显示
static bool _isLoad = false; //防止load多次加载
static bool _isMove = false; //防止load多次加载
static bool _isAutoClose = false; //是否是一秒后自动关闭footer
Listener buildSmartRefresh(State state) {
return Listener(
onPointerDown: (p) {
state.setState(() {
_isLoad = true;
_isFooter = true;
print("onPointerDown$_isLoad");
});
},
onPointerMove: (p) {
state.setState(() {
_isMove = true;
});
},
onPointerUp: (p) {
_isMove = false;
if (!_isAutoClose) {
state.setState(() {
_isAutoClose = true;
_isFooter = false;
});
}
},
child: this,
);
}
Function onSmartRefreshCallback(onRefresh,EasyRefreshController controller) {
return () async {
await Future.delayed(Duration(seconds: 0), () {
onRefresh();
controller.resetLoadState();
});
};
}
Function onSmartLoadCallback(onLoad,state,EasyRefreshController controller) {
return _isFooter
? () async {
await Future.delayed(Duration(seconds: 0), () {
print('onLoad');
print("onLoad$_isLoad");
if (_isLoad) {
_isLoad = false;
onLoad();
loadingBottomControl(state);
} else {
controller.finishLoad();
}
});
}
: null;
}
void loadingBottomControl(State state) {
Future.delayed(Duration(milliseconds: 1000), () {
state.setState(() {
if(_isMove) {
_isAutoClose = false;
} else {
_isAutoClose = true;
_isFooter = false;
}
});
});
}
}
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'SmartRefresh.dart';
void main() => runApp(MyApp());
//调用EasyRefresh示例
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
// App名字
title: 'EasyRefresh',
// App主题
theme: new ThemeData(
primarySwatch: Colors.orange,
),
// 主页
home: _Example(),
localizationsDelegates: [
GlobalEasyRefreshLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
);
}
}
class _Example extends StatefulWidget {
@override
_ExampleState createState() {
return _ExampleState();
}
}
class _ExampleState extends State<_Example> {
EasyRefreshController _controller;
// 条目总数
int _count = 1;
@override
void initState() {
super.initState();
_controller = EasyRefreshController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("EasyRefresh"),
),
body: _easyRefreshState().buildSmartRefresh(this));
}
EasyRefresh _easyRefreshState(){
EasyRefresh refresh = EasyRefresh();
refresh = EasyRefresh.custom(
enableControlFinishRefresh: false,
enableControlFinishLoad: true,
controller: _controller,
header: ClassicalHeader(),
footer: ClassicalFooter(),
onRefresh: refresh.onSmartRefreshCallback(onRefresh,_controller),
onLoad: refresh.onSmartLoadCallback(onLoad, this,_controller),
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
width: 60.0,
height: 60.0,
child: Center(
child: Text('$index'),
),
color: index % 2 == 0
? Colors.grey[300]
: Colors.transparent,
);
},
childCount: _count,
),
),
],
);
return refresh;
}
void onRefresh() {
setState(() {
_count = 1;
});
}
void onLoad() {
setState(() {
_count += 1;
});
_controller.finishLoad(noMore: _count >= 10);
}
}
github源码地址:
https://github.com/gonglipeng/SmartRefresh.git
更多推荐
所有评论(0)