一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。
第一部 加载网络数据效果:
第二部分 上拉加载更多数据效果:
本章学习目标:
1.数据用之前写好的productModel。
2.封装上拉加载控件
本章分两部分来做,首先先获取数据,数据赋值给UI控件,第二部分做上拉加载更多。然后跟着出现的bug逐步完善。
第一部分
第一步:封装上拉加载控件
LoadingWidget 源码
import 'package:flutter/material.dart';
class LoadingWidget extends StatelessWidget {
const LoadingWidget({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(
strokeWidth: 1.0,
),Text(
'加载中...',
style: TextStyle(fontSize: 16.0),
)
],
),
),
);;
}
}
第二步:回到productList.dart文件
import 'package:flutter_app/widget/LoadingWidget.dart';
import 'package:dio/dio.dart';
import '../config/Config.dart';
import '../model/ProductModel.dart';
新建属性
//数据
List _productList = [];
//页数 用于请求
int _page = 1;
//请求一页返回的个数 限制8个
int _pageSize=8;
/*
排序:价格升序 sort=price_1 价格降序 sort=price_-1 销量升序 sort=salecount_1 销量降序 sort=salecount_-1
*/
String _sort = "";
编写获取网络数据的方法
//获取商品列表的数据
_getProductListData() async {
var api =
'${Config.domain}api/plist?cid=${widget.arguments["cid"]}&page=${this._page}&sort=${this._sort}&pageSize=${this._pageSize}';
var result = await Dio().get(api);
//获取数据后存储到模型里面
var productList = new ProductModel.fromJson(result.data);
//合并数据
setState(() {
this._productList.addAll(productList.result);//合并数据
});
}
进入控制器调用网络数据的方法
@override
void initState() {
super.initState();
_getProductListData();
}
在_productListWidget方法的最外面添加判断用于显示加载控件
if (this._productList.length > 0) {
//抽取 把之前的代码写在里面
} else {
//加载中
return LoadingWidget();
}
修改显示数据的地方
//处理图片
String pic=this._productList[index].pic;
pic=Config.domain+pic.replaceAll('\\', '/');
"${pic}",
文本
"${this._productList[index].title}",
富文本
"¥${this._productList[index].price}",
数组个数
itemCount: this._productList.length,
到这里显示数据已经OK了 下面是上拉加载更多
第二部分
1.写在_ProductListPageState里面
//用于上拉分页 用于上拉加载更多用的
ScrollController _scrollController = ScrollController(); //listview 的控制器
2.监听接近底部的时候调用获取网络数据的方法 写在 initState方法里面
@override
void initState() {
super.initState();
_getProductListData();
//监听滚动条滚动事件
_scrollController.addListener((){
//_scrollController.position.pixels //获取滚动条滚动的高度
//_scrollController.position.maxScrollExtent //获取页面高度
if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-20){
_getProductListData();
}
});
}
3.添加监听控制器
controller: _scrollController,
编写地方提示
4.获取数据成功页数递增一
this._page++;//页数递增1
运行
添加加载中下面有一个菊花动画,写一个方法
//显示加载中的圈圈
Widget _showMore(index){
return (index==this._productList.length-1)?LoadingWidget():Text("");
}
1.这句话写在 Divider(height: 20),的下面 自己搜索一下
注意 Divider(height: 20) 记得后面加逗号不然会报错。
_showMore(index)//这句话放在底部是用于显示 菊花 或者 我是有底线的
BUG
现在有个BUG 上拉加载发现数据重复加载,新建属性falg
//解决上拉重复请求的问题 加载的时候不能进来重复获取数据 造成重复加载
bool flag=true;
2.写在if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-20){里面 搜索一下
替换 _getProductListData(); 其实就是外面包裹一个if判断
//加载的时候不能进来重复获取数据 造成重复加载
if(this.flag){ _getProductListData(); }
3.写在获取网络数据的方法里面 进来就锁住他 _getProductListData() async {写在这里下面
setState(() {
//进来设置为false 不能重复加载
this.flag=false;
});
4.写在 this._page++;//页数递增1 下面搜搜一下
this.flag=true;//加载数据完成 设置为true 加载上拉加载数据
运行
BUG
现在有一个BUG,没有数据的时候最底部有一值菊花在转(可以加载就有菊花转,没有数据的时候就显示我是有底线的)
1.创建一个属性
//是否有数据 有数据显示圈圈加载 无就显示我是有底线的
bool _hasMore=true;
2.加载数据时增加多一个判断this._hasMore
if(this.flag && this._hasMore){
_getProductListData();
}
3.合并数据下面修改一下 var productList = new ProductModel.fromJson(result.data); 这句话下面 搜索一下
//加载回来的数据不够一页 显示我是有底线的
if(productList.result.length<this._pageSize){
setState(() {
this._productList.addAll(productList.result);//合并数据
this._hasMore=false;//数据到底部 设置为false 用于显示我是有底线的
this.flag=true;//加载数据完成 设置为true 加载上拉加载数据
});
}else{
setState(() {
this._productList.addAll(productList.result);//合并数据
this._page++;//页数递增1
this.flag=true;//加载数据完成 设置为true 加载上拉加载数据
});
}
4.修改整个方法
//显示加载中的圈圈
Widget _showMore(index){
if(this._hasMore){ //有数据就显示 加载的菊花
return (index==this._productList.length-1)?LoadingWidget():Text("");
}else{ //没有数据显示我是有底线的
return (index==this._productList.length-1)?Text("--我是有底线的--"):Text("");;
}
}