DEV Community

Chintan Gohil
Chintan Gohil

Posted on

flutter load more

//skip and limit
`import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class PaginatedApiListView extends StatefulWidget {
@override
_PaginatedApiListViewState createState() => _PaginatedApiListViewState();
}

class _PaginatedApiListViewState extends State {
final ScrollController _scrollController = ScrollController();
List _products = [];
int _currentPage = 1;
final int _limit = 10;
bool _isLoading = false;
bool _hasMore = true;

@override
void initState() {
super.initState();
_fetchProducts();

_scrollController.addListener(() {
  if (_scrollController.position.pixels >=
      _scrollController.position.maxScrollExtent - 200 &&
      !_isLoading &&
      _hasMore) {
    _fetchProducts();
  }
});
Enter fullscreen mode Exit fullscreen mode

}

Future _fetchProducts() async {
setState(() {
_isLoading = true;
});

final skip = (_currentPage - 1) * _limit;
final response = await http.get(
  Uri.parse('https://dummyjson.com/products?limit=$_limit&skip=$skip'),
);

if (response.statusCode == 200) {
  final data = json.decode(response.body);
  final List<dynamic> newProducts = data['products'];

  setState(() {
    _currentPage++;
    _products.addAll(newProducts);
    _hasMore = _products.length < data['total']; // total = 100
    _isLoading = false;
  });
} else {
  setState(() {
    _isLoading = false;
  });

  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('Failed to load data')),
  );
}
Enter fullscreen mode Exit fullscreen mode

}

@override
void dispose() {
_scrollController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Paginated Products')),
body: ListView.builder(
controller: _scrollController,
itemCount: _products.length + (_isLoading || _hasMore ? 1 : 0),
itemBuilder: (context, index) {
if (index < _products.length) {
final product = _products[index];
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(product['thumbnail']),
),
title: Text(product['title']),
subtitle: Text("\$${product['price']}"),
);
} else {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Center(child: CircularProgressIndicator()),
);
}
},
),
);
}
}
`

| List (array) | List data = jsonDecode(...) | posts.addAll(data); |
| Single Object | Map data = jsonDecode(...) | posts.add(data); |
| Object with List inside key | Map json = jsonDecode(...); List data = json['data']; | posts.addAll(data); |

'import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

class LastDemo extends StatefulWidget {
const LastDemo({super.key});

@override
State createState() => _DemoState();
}

class _DemoState extends State {
List posts = [];
bool _isloading = false;
bool hasmore = true;
int currenpage = 1;
final int limit = 20;
final ScrollController scrollController = ScrollController();

@override
void initState() {
super.initState();
fetchPosts();
scrollController.addListener(_scrollListener);
}

void _scrollListener() {
if (scrollController.position.pixels >=
scrollController.position.maxScrollExtent - 200 &&
!_isloading &&
hasmore) {
fetchPosts();
}
}

Future fetchPosts() async {
setState(() {
_isloading = true;
});

final response = await http.get(Uri.parse(
    'https://jsonplaceholder.typicode.com/posts?_page=$currenpage&_limit=$limit'));

if (response.statusCode == 200) {
  final List<dynamic> data = jsonDecode(response.body);

  setState(() {
    currenpage++;
    posts.addAll(data);
    _isloading = false;
    if (data.length < limit) {
      hasmore = false;
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

}

@override
void dispose() {
scrollController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Paginated Posts")),
body: ListView.builder(
controller: scrollController,
itemCount: posts.length + (_isloading && hasmore ? 1 : 0),
itemBuilder: (context, index) {
if (index < posts.length) {
final post = posts[index];
return ListTile(
title: Text(post['title']),
subtitle: Text(post['body']),
);
} else {
return const Padding(
padding: EdgeInsets.all(12),
child: Center(child: CircularProgressIndicator()),
);
}
},
),
);
}
}
'

Top comments (0)