Skip to main content

Flutter pagination tutorial

option 1


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

// API Service
class ApiService {
  static const String baseUrl = "https://jsonplaceholder.typicode.com";

  static Future<List<dynamic>> fetchData(int page, int limit) async {
    final response = await http.get(Uri.parse("$baseUrl/posts?_page=$page&_limit=$limit"));

    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      throw Exception("Failed to load data");
    }
  }
}

// GetX Controller for Pagination
class PaginationController extends GetxController {
  var items = <dynamic>[].obs;
  var page = 1.obs;
  final int limit = 10;
  var isLoading = false.obs;
  var hasMore = true.obs;
  ScrollController scrollController = ScrollController();

  @override
  void onInit() {
    fetchItems();
    scrollController.addListener(() {
      if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 100) {
        fetchItems(); // Load more data when close to bottom
      }
    });
    super.onInit();
  }

  Future<void> fetchItems() async {
    if (isLoading.value || !hasMore.value) return;

    isLoading(true);
    try {
      var newItems = await ApiService.fetchData(page.value, limit);
      if (newItems.isNotEmpty) {
        items.addAll(newItems);
        page.value++;
      } else {
        hasMore(false); // No more data
      }
    } catch (e) {
      print("Error: $e");
    } finally {
      isLoading(false);
    }
  }
}

// UI: Home Page with Infinite Scrolling using ScrollController
class HomePage extends StatelessWidget {
  final PaginationController controller = Get.put(PaginationController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Pagination with ScrollController")),
      body: Obx(() {
        if (controller.items.isEmpty && controller.isLoading.value) {
          return Center(child: CircularProgressIndicator());
        }

        return ListView.builder(
          controller: controller.scrollController,
          itemCount: controller.items.length + (controller.hasMore.value ? 1 : 0),
          itemBuilder: (context, index) {
            if (index == controller.items.length) {
              return Center(
                child: Padding(
                  padding: EdgeInsets.all(8.0),
                  child: CircularProgressIndicator(),
                ),
              );
            }
            return ListTile(
              title: Text(controller.items[index]['title']),
            );
          },
        );
      }),
    );
  }
}

void main() {
  runApp(GetMaterialApp(
    home: HomePage(),
    debugShowCheckedModeBanner: false,
  ));
}




option 2

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

// API Service
class ApiService {
  static const String baseUrl = "https://jsonplaceholder.typicode.com";

  static Future<List<dynamic>> fetchData(int page, int limit) async {
    final response = await http.get(Uri.parse("$baseUrl/posts?_page=$page&_limit=$limit"));
    
    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      throw Exception("Failed to load data");
    }
  }
}

// GetX Controller for Pagination
class PaginationController extends GetxController {
  var items = <dynamic>[].obs;
  var page = 1.obs;
  final int limit = 10;
  var isLoading = false.obs;
  var hasMore = true.obs;

  @override
  void onInit() {
    fetchItems();
    super.onInit();
  }

  Future<void> fetchItems() async {
    if (isLoading.value || !hasMore.value) return;

    isLoading(true);
    try {
      var newItems = await ApiService.fetchData(page.value, limit);
      if (newItems.isNotEmpty) {
        items.addAll(newItems);
        page.value++;
      } else {
        hasMore(false); // No more data
      }
    } catch (e) {
      print("Error: $e");
    } finally {
      isLoading(false);
    }
  }
}

// UI: Home Page with Infinite Scrolling
class HomePage extends StatelessWidget {
  final PaginationController controller = Get.put(PaginationController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Pagination with GetX")),
      body: Obx(() {
        if (controller.items.isEmpty && controller.isLoading.value) {
          return Center(child: CircularProgressIndicator());
        }

        return NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification scrollInfo) {
            if (!controller.isLoading.value &&
                scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
              controller.fetchItems(); // Load more data when reaching bottom
            }
            return false;
          },
          child: ListView.builder(
            itemCount: controller.items.length + (controller.hasMore.value ? 1 : 0),
            itemBuilder: (context, index) {
              if (index == controller.items.length) {
                return Center(
                  child: Padding(
                    padding: EdgeInsets.all(8.0),
                    child: CircularProgressIndicator(),
                  ),
                );
              }
              return ListTile(
                title: Text(controller.items[index]['title']),
              );
            },
          ),
        );
      }),
    );
  }
}

void main() {
  runApp(GetMaterialApp(
    home: HomePage(),
    debugShowCheckedModeBanner: false,
  ));
}



option 3


Comments

Popular posts from this blog

Building a Dynamic Product List with GetX in Flutter

Building a Dynamic Product List with GetX in Flutter Learn how to create a responsive product screen using GetX in Flutter. This tutorial covers API integration, pagination, cart management, and quantity selection with efficient state management. Perfect for building an e-commerce app! class ProductScreenController extends GetxController{      RxList<Product> productList = <Product>[].obs;   RxList<Product> cartList = <Product>[].obs;   RxMap<int , int> quantityMap = <int , int>{}.obs;   RxMap<int, bool> showQuantitySelector = <int, bool>{}.obs; // ✅ Track Visibility of Quantity Selector   RxBool isLoading = false.obs;   RxBool isLoadingMore = false.obs;   final Dio dio = Dio();   int limit = 10;   int skip = 0;   bool hasMore = true; // ✅ Track if more data is available   @override   void onInit() {  // ✅ Automatically Call API when Controller initializes   ...

send data controller to provider

 send data controller to provider import 'package:flutter/material.dart'; import 'model.dart'; class TaskProvider extends ChangeNotifier {   List<Task> _tasks = [];   List<Task> get tasks => _tasks;   // Create operation   void addTask(Task task) {     _tasks.add(task);     notifyListeners();   }   // Read operation (already accessible via getter tasks)   // Update operation   void updateTask(Task task) {     // Find the task in the list and update it     int index = _tasks.indexWhere((t) => t.id == task.id);     if (index != -1) {       _tasks[index] = task;       notifyListeners();     }   }   // Delete operation   void deleteTask(String id) {     _tasks.removeWhere((task) => task.id == id);     notifyListeners();   } } class Task {   String id;   String title;   bool completed...