我想分部分获取所有无限列表视图数据,这意味着最初它加载 10 个数据项,滚动更多时它应该获取接下来的 10 个项目。 我正在从我的 Laravel api 获取数据,并且在我的 Laravel api 端点中没有 per_page 选项,所以请帮助我集成加载列表视图数据的更多选项。 这是我的列表数据。
List<Category> _categoryList = List<Category>();
CategoryService _categoryService = CategoryService();
bool isLoading = true;
@override
void initState() {
super.initState();
_getAllCategories();
}
_getAllCategories() async {
var categories = await _categoryService.getCategories();
var result = json.decode(categories.body);
result['data'].forEach((data) {
var model = Category();
model.id = data["id"];
model.name = data["categoryName"];
model.icon = data["categoryIcon"];
setState(() {
_categoryList.add(model);
isLoading = false;
});
});
}
我正在简单的 ListTile 中获取所有数据。
child: ListView.builder(
itemCount: //_categoryList.length,
itemBuilder: (context, index) {
return ListTile(
title: _categoryList.name
);
},
),
所以我有一个技巧,并且正在我的项目中使用它。这里我们需要的是当我们位于列表末尾时加载更多数据。为此,我们只能使用
ListView.builder()
:
child: ListView.builder(
itemCount: _categoryList.length + 1,
itemBuilder: (context, index) {
if(index == _categoryList.length){
// loadMore();
// return Loading();
}
return ListTile(
title: _categoryList.name
);
}),
所以我们要做的就是将
_categoryList.length + 1
设置为 itemCount
。如果 _categoryList.length
是 10
,那么我们将在 11
中有 ListView
项,并且索引范围将为 0 - 10
。因此,在 builder
内部,我们检查 index
是否等于 _categoryList.length
,即 10
。如果 index
等于 _categoryList.length
的长度,那么我们就在 List
的末尾,我们可以简单地调用一些函数来从 Api 加载更多数据或显示加载小部件。
我想我的问题是对的,这样当用户到达列表末尾时,您可以简单地延迟加载数据,而无需使用任何第三方库。
这个过程称为分页。 Laravel 提供了一个功能来检查 Laravel 中的分页
例如
$users = DB::table('users')->paginate(15);// 15 is limit per page
并检查一下 flutter dev 中的 Paging lib。
我创建了一个示例来使用 Web 服务加载更多数据 你可以看这个例子,你可以为你实现json数据。
https://android-pratap.blogspot.com/2018/12/flutter-infinite-listview-using.html
import 'package:akeepo/randomuser_infinitelist.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: InfiniteUsersList(),
);
}
}
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class InfiniteUsersList extends StatefulWidget {
static String tag = 'users-page';
@override
State<StatefulWidget> createState() {
return new _InfiniteUsersListState();
}
}
class _InfiniteUsersListState extends State<InfiniteUsersList> {
List<User> users = new List<User>();
ScrollController _scrollController = new ScrollController();
bool isPerformingRequest = false;
int pageNumber = 0;
@override
void initState() {
super.initState();
// Loading initial data or first request to get the data
_getMoreData();
// Loading data after scroll reaches end of the list
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMoreData();
}
});
}
// to show progressbar while loading data in background
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isPerformingRequest ? 1.0 : 0.0,
child: new CircularProgressIndicator(),
),
),
);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
// Webservice request to load 20 users data using paging
Future<List<User>> _getUsers() async {
List<User> users = new List<User>();
setState(() {
pageNumber++;
});
String url =
"https://api.randomuser.me/?page=$pageNumber&results=20&seed=abc";
print(url);
var response = await http.get(url);
var jsonData = json.decode(response.body);
print(jsonData);
var usersData = jsonData["results"];
for (var user in usersData) {
User newUser = User(user["name"]["first"] + user["name"]["last"],
user["email"], user["picture"]["large"], user["phone"]);
users.add(newUser);
}
return users;
}
_getMoreData() async {
if (!isPerformingRequest) {
setState(() {
isPerformingRequest = true;
});
List<User> newEntries = await _getUsers(); //returns empty list
if (newEntries.isEmpty) {
double edge = 50.0;
double offsetFromBottom = _scrollController.position.maxScrollExtent -
_scrollController.position.pixels;
if (offsetFromBottom < edge) {
_scrollController.animateTo(
_scrollController.offset - (edge - offsetFromBottom),
duration: new Duration(milliseconds: 500),
curve: Curves.easeOut);
}
}
setState(() {
users.addAll(newEntries);
isPerformingRequest = false;
});
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Users',
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
body: Container(
child: ListView.builder(
shrinkWrap: true,
controller: _scrollController,
itemCount: users.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == users.length) {
return _buildProgressIndicator();
} else {
return ListTile(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
UserDetailPage(users[index])));
},
title: Text(users[index].fullName),
subtitle: Text(users[index].mobileNumber),
leading: CircleAvatar(
backgroundImage: NetworkImage(users[index].imageUrl)),
);
}
})),
);
}
}
class User {
final String fullName;
final String email;
final String imageUrl;
final String mobileNumber;
User(this.fullName, this.email, this.imageUrl, this.mobileNumber);
}
// User Detail Page
class UserDetailPage extends StatelessWidget {
final User user;
UserDetailPage(this.user);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("User Details"),
),
body: Center(
child: Text(
user.fullName,
style: TextStyle(fontSize: 35.0),
),
),
);
}
}
我在此基础上建立了自己的逻辑。 项目数=列表.长度+1。 因此,如果列表长度为 4,则意味着我们有 4+1 个项目。
indexes = 0 1 2 3 4
。
列表项索引为 0 1 2 3
ListView(
itemBuilder:
if(index==listLength){ //index=5 the button position
button
}else {
//if current index is 0 let it.
//else if index is equal to list length subtract 1 from it to get last item in the list
//else let index as it is
var i = index==0?0: index==list.length? index-1:index;
var item = list[i];
}
)