Reputation: 113
I'm trying to implement a lazy loading listview in my Flutter app. Basically when user scrolls to bottom, we fetch more data from the server. Let's say there are totally 100 items and I fetch 10 of them at the beginning.
The problem is, some devices such as tablets are large enough to display all the 10 items at once. So Flutter makes the listview unscrollable. Therefore we are not able to reach the bottom and fetching is not triggered.
What is the best approach to trigger fetching automatically on such use cases?
void _scrollListener() {
// Check if we are at the bottom of the list and loading isn't in progress
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !_isLoading) {
_loadMoreItems();
}
}
Future<void> _loadMoreItems() async {
setState(() {
_isLoading = true;
});
// Simulate a network request (wait 2 seconds)
await Future.delayed(Duration(seconds: 2));
// Fetch more items
final newItems = List.generate(10, (index) => _items.length + index);
setState(() {
_isLoading = false;
_items.addAll(newItems);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Lazy Loading ListView')),
body: ListView.builder(
controller: _scrollController,
itemCount: _items.length + 1, // +1 for the loading indicator
itemBuilder: (context, index) {
if (index == _items.length) {
// Show loading indicator at the bottom when more items are being fetched
return _isLoading
? Center(child: CircularProgressIndicator())
: SizedBox.shrink();
}
return ListTile(title: Text('Item ${_items[index]}'));
},
),
);
}
Upvotes: 1
Views: 60
Reputation: 801
I would recommend EasyRefresh to you
EasyRefresh(
onRefresh: () async {
....
},
onLoad: () async {
....
},
child: ListView(),
);
Upvotes: 0
Reputation: 412
You can use layout builder and depends on screen size. I used like this. You can make configuration for yours, like get 10 items for small screen, 20 for big screen sizes.
Widget _buildScreenLayout(BuildContext context) => Container(
height: context.height,
margin: const EdgeInsets.all(10),
child: LayoutBuilder(
builder: (context, constraints) {
final isSizeSmall = MediaQuery.sizeOf(context).width < 600;
if (isSizeSmall) {
return _buildLayout();
} else {
return _buildBigScreenLayout();
}
},
),
);
Upvotes: 2
Reputation: 954
i have updated code please try this if it works.
import 'package:flutter/material.dart';
class LazyLoadingList extends StatefulWidget {
const LazyLoadingList({super.key});
@override
State<LazyLoadingList> createState() => _LazyLoadingListState();
}
class _LazyLoadingListState extends State<LazyLoadingList> {
List<int> items = List.generate(20, (index) => index); // Initial list
final ScrollController _scrollController = ScrollController();
bool isLoading = false;
int totalItems = 100; // Simulated total items available
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
}
void _onScroll() {
if (_scrollController.position.pixels >=
_scrollController.position.maxScrollExtent - 200 &&
!isLoading &&
items.length < totalItems) {
_loadMoreItems();
}
}
Future<void> _loadMoreItems() async {
if (!mounted) return;
setState(() {
isLoading = true;
});
// Simulate network delay
await Future.delayed(const Duration(seconds: 1));
if (!mounted) return;
setState(() {
final newItems = List.generate(
20,
(index) => items.length + index,
);
items.addAll(newItems);
isLoading = false;
});
}
@override
void dispose() {
_scrollController.removeListener(_onScroll);
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Lazy Loading List'),
),
body: ListView.builder(
controller: _scrollController,
itemCount: items.length + (isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index == items.length && isLoading) {
return const Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
),
);
}
return ListTile(
title: Text('Item ${items[index]}'),
);
},
),
);
}
}
void main() {
runApp(const MaterialApp(home: LazyLoadingList()));
}
Upvotes: 2