Springboot(省略,自己写接口,以往文章有)
Flutter:
导包:flutter pub add http //与接口进行交互
1、生成对象类(怎么叫我没深究自己知道就行)
网站:https://app.quicktype.io/ //要访问的话,也穿过人山人海的前一句歌词是什么
将数据库的数据导出Json然后复制黏贴到左边生成,剩下右边要求不懂自己看
2、main类(记得要把http包 as http)
要Stateful来主要实现
定义用到的变量(放数据):List<T>,如果你是直接获取全部数据Select all基本不用定义其他变量,但是分页操作你就要定义一个全局的PageNum来方便加载新数据。
先写一个异步操作方法来访问你自己写好的接口url来进行访问,final http,Response response=await http.get(Uri.parse('...你的URL'));
写判断,当成功访问,respone.statusCode==200之后需要返回什么?在里面写一个当你获取到第二页的数据就应该添加而不是直接覆盖掉原来的数据,使用addAll来进行添加,主要方法是生成对象类里的操作方法,使用它将获得的数据转换成List<T>来存储 adInfoList=...FromJson(jsonData);
在此之前,你可以使用response.body存储访问URL获得的数据。
initState初始化,需要使用另一个异步方法_initAdInfoList,因为initState无法定义成异步;await _getDataFromUrl(pageNum); setState(){}; setState最重要,不可省略,起到刷新页面的作用,滑到底部加载需要添加一个ScrollController,定义一个大的ScrollController在Stateful继承方法下,然后在initState使用sc.addListener{ ...}里面具体怎么实现监听你就要自己去了解了,不难,了解其属性即可。
接下来就是自己写ListView.builder自己遍历数据,下拉刷新的话用RefreshIndicator套住,设置deplacement下拉多少进行刷新就可以了,看着比较复杂,其实很简单,ItemCount填上adInfoList.length,itemBuilder为遍历主题,搞一个adInfo来方便遍历,fianl adInfo=adInfoList![index],!就是如果出现空就会抛出异常。
接下来就是排版问题,注意不要乱套组件,编译不会报错但也会出现运行程序时什么都看不见!
代码:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'models/adinfo.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: "",
home: TestDown(),
);
}
}
class TestDown extends StatefulWidget {
const TestDown({super.key});
@override
State<TestDown> createState() => _TestDownState();
}
class _TestDownState extends State<TestDown> {
ScrollController sc = ScrollController();
List<AdInfo>? adInfoList;
int pageNum = 1;
Widget divider = const Divider(
thickness: 5,
color: Colors.blueGrey,
);
Future<void> _getDataFromUrl(int askPage) async {
askPage = pageNum;
final http.Response response = await http.get(
Uri.parse('....:.../selectlimited?page=$askPage'));
if (response.statusCode == 200) {
final jsonData = response.body;
if (pageNum > 1) {
//当pageNum>1的时候选择添加数据到类中,而不是直接覆盖
adInfoList?.addAll(adInfoFromJson(jsonData));
} else {
//将数据存储到adInfoList中
adInfoList = adInfoFromJson(jsonData);
}
}
}
Future<void> _initAdInfoList() async {
await _getDataFromUrl(pageNum);
setState(() {});
}
Future<void> _onRefresh() async {
await Future.delayed(const Duration(seconds: 1));
setState(() {
_getDataFromUrl(pageNum++);
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
_initAdInfoList();
sc.addListener(() {
if (sc.position.hasPixels == sc.position.atEdge) {
print('到底');
_onRefresh();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("ReviewUp_Down"),
),
body: RefreshIndicator(
displacement: 10,
onRefresh: _onRefresh,
child: ListView.separated(
controller: sc,
itemBuilder: (context, index) {
final adInfo = adInfoList![index];
return ListTile(
dense: true,
title: Text('Issue: ${adInfo.issue}'),
subtitle: Column(
children: [
Text('TotalIn: ${adInfo.totalIn}'),
Text('Wnums: ${adInfo.wnums}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
Text('Issue: ${adInfo.issue}'),
const SizedBox(
height: 20,
)
],
),
);
},
separatorBuilder: (context, index) {
return divider;
},
itemCount: adInfoList?.length ?? 0),
),
);
}
}