laravel - 你好!Flutter中如何实现分页,
问题描述
我想在颤振中集成分页,我已经完成并且它正在工作,但是当它到达底部并加载新数据时,它预设了旧数据,这没有任何意义,所以如何用新数据持久化旧数据好吧,这是我的完整代码,我只是不知道他们用futre builder将数据保存在列表中的方法,当它到达bootom时它正在调用该函数并用新数据重建列表,旧数据消失在空中
import 'dart:io';
import 'package:flutter/material.dart';
import 'product/products.dart';
import 'package:provider/provider.dart';
import 'utils/auth.dart';
import 'navigation.dart';
import 'package:lsawf/utils/api_util.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'product/productdetail.dart';
void main() {
runApp(ChangeNotifierProvider(
create: (BuildContext context) => AuthProvider(),
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MY Finance',
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late Future<List<Product>> futureBooks;
var _url = Uri.parse(ApiUtility.Main_Url + '/products');
var nexturl;
ScrollController _scrollController = new ScrollController();
//determine if all data has been recieved
var loadCompleted = false;
List<Product> tempList = [];
var mycontroler = TextEditingController();
@override
void initState() {
super.initState();
readToken();
data = getData(_url);
scrollindecator();
}
void scrollindecator() {
_scrollController.addListener(
() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
print('reach to bottom botton');
if (!loadCompleted) {
setState(() {
//add more data to list
data = getData(Uri.parse(nexturl));
});
}
}
},
);
}
Future<List<Product>> getData(_url) async {
List<Product> products = <Product>[];
final response = await http.get(_url, headers: {});
if (response.statusCode == 200) {
// ignore: unused_local_variable
var data3 = json.decode(response.body)['links'];
print(data3);
if (data3['next'] != null) {
nexturl = data3['next'];
print(nexturl);
} else {
loadCompleted = true;
}
var data = List<Map<String, dynamic>>.from(json.decode(response.body)['data']);
for (int i = 0; i < data.length; i++) {
products.add(Product.fromJson(data[i]));
}
return products;
} else {
throw SocketException('Make sure you have an internet connection');
}
}
late Future<List<Product>> data;
void dispose() {
super.dispose();
_scrollController.dispose();
mycontroler.dispose();
}
void readToken() async {
await Provider.of<AuthProvider>(context, listen: false).tryToken();
}
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
double text = MediaQuery.textScaleFactorOf(context);
return Scaffold(
appBar: AppBar(
title: Text(
'Mosque Giving',
style: TextStyle(color: Color(0XFF1A1A1A)),
),
centerTitle: true,
elevation: 0,
backgroundColor: Color(0xFF69389a),
),
body: ListView(
controller: _scrollController,
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text(
'Giving to your local mosque made easy!',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: text * 16,
),
),
SizedBox(
height: height * 0.03,
),
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.0),
color: Colors.grey[200],
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0),
blurRadius: 1.0,
),
],
),
child: TextField(
controller: mycontroler,
decoration: InputDecoration(
icon: Padding(
padding: EdgeInsets.only(left: 12.0),
child: Icon(
Icons.search,
color: Colors.grey,
),
),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
),
),
),
SizedBox(width: width * 0.00),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.0),
color: Colors.grey[200],
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0),
blurRadius: 1.0,
),
],
),
child: SizedBox(
height: height * 0.06,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0.0),
),
primary: Color(0xFF69389a)),
onPressed: () {
if (mycontroler.text == '') {
final snackBar = SnackBar(
content: Text('Please enter a keyword!'));
ScaffoldMessenger.of(context)
.showSnackBar(snackBar);
} else {}
},
child: Text('search')),
),
),
],
),
SizedBox(
height: 10.0,
),
Row(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'All Mosque',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
],
),
SizedBox(
height: 10.0,
),
],
),
],
),
),
FutureBuilder<List<Product>>(
future: data,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
physics: ScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.all(8),
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
Product product = snapshot.data![index];
return Padding(
padding: const EdgeInsets.only(bottom: 15),
child: InkWell(
child: Card(
elevation: 0,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.grey[200],
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0),
blurRadius: 1.0,
),
],
),
// color: Colors.black12,
padding: EdgeInsets.all(2),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: double.infinity,
child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 1),
width: double.infinity,
child: Image(
image: NetworkImage(
ApiUtility.Assest_Url +
product.dealimage),
height: 180,
fit: BoxFit.fitWidth),
),
],
),
),
Container(
width: double.infinity,
child: Stack(
alignment: Alignment.bottomLeft,
children: <Widget>[
Container(
// color: Colors.black.withOpacity(0.5),
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding:
const EdgeInsets.all(1.0),
child: Text(
product.title,
style: TextStyle(
fontSize: 15,
fontWeight:
FontWeight.bold,
),
)),
Padding(
padding:
const EdgeInsets.fromLTRB(
0, 8, 0, 8),
child: RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Icon(
Icons.location_on,
size: 18,
color: Color(
0xFF69389a)),
),
TextSpan(
text: product.address,
style: TextStyle(
color: Colors
.black)),
],
),
),
),
Row(
children: <Widget>[
Container(
height: 40,
child: ElevatedButton(
style: ElevatedButton
.styleFrom(
primary: Color(
0xFF69389a)),
onPressed: () {},
child: Text('Donate Now'),
),
),
SizedBox(width: 3),
Container(
height: 40,
child: ElevatedButton(
style: ElevatedButton
.styleFrom(
primary: Color(
0xFF69389a)),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
new Productdetails(
prd:
new Product(
id: product
.id,
address:
product
.address,
title: product
.title,
category:
product
.category,
dealimage:
product
.dealimage,
description:
product
.description,
slug: product
.slug,
))));
},
child:
Text('View Details'),
),
),
],
)
],
),
),
],
),
),
],
),
),
),
),
);
},
);
} else if (snapshot.hasError) {
return Center(child: Text("${snapshot.error}"));
}
return Center(child: CircularProgressIndicator());
}),
],
// This trailing comma makes auto-formatting nicer for build methods.
),
drawer: Container(width: width * 0.5, child: Navigation()),
);
}
}
解决方案
推荐阅读
- mysql - 我的 Apache 和 Mysql 没有在 xampp 中启动
- authentication - 使用私钥的 ssh 身份验证问题
- java - 如何使用 JAVA 在 S3 文件中更新 CSV 文件的标题
- google-cloud-identity - API - 客户 ID 不容易找到 - 请支持 my_customer
- google-sheets-formula - 查找包含键的所有行并连接单元格值
- cordova - 离子文件插件在根内部存储上创建目录时出错
- html - CSS网格消除间隙
- python - 如何限制单个唯一 ID 可以拥有的行数?/文本游戏的有限游戏库存
- shell - Makefile:如何正确扩展 shell 函数中的变量?
- ios - Two different values from the same kSecAttrAccount in Keychain