Effortlessly Make Network Requests in Flutter with Dio Library - Flutter

This is a Flutter application that uses the Dio package to make HTTP requests to an API and display the results in a ListView.
The Post class represents a single post object that is returned from the API. It has three properties: id, title, and body. It also has a factory method fromJson that creates a Post object from a JSON object.

The ApiService class is responsible for making HTTP requests to the API. It creates a Dio object with some default options, including the API base URL and timeout durations. It also adds an interceptor Log to log the request and response details.

The fetchPosts method in the ApiService class sends a GET request to the /posts endpoint of the API and waits for a response. If the request is successful, it extracts the data property from the response and converts it to a list of Post objects using the map method and the fromJson factory method. Finally, it returns the list of Post objects. If the request fails, it throws an exception with an error message.

The Log class is an interceptor that logs the request and response details using the debugPrint method.

The HomePage class is a stateless widget that displays a ListView of posts. It creates an instance of ApiService and calls the fetchPosts method to get the list of posts. It uses a FutureBuilder widget to asynchronously display the data in the ListView. If the data is available, it creates a ListView.builder widget with each post represented by a ListTile. If there is an error, it displays an error message. If the data is not yet available, it displays a loading indicator.

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';


class Post {
  final int id;
  final String title;
  final String body;

  Post({required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

class ApiService {
  final Dio _dio = Dio(BaseOptions(
    baseUrl: 'https://jsonplaceholder.typicode.com',
    connectTimeout: const Duration(seconds: 5),
    receiveTimeout: const Duration(seconds: 3),
    responseType: ResponseType.json,
  ))
    ..interceptors.addAll([Log()]);

  Future<List<Post>> fetchPosts() async {
    try {
      final response = await _dio.get('/posts');
      final data = response.data as List;
      final users = data.map((json) => Post.fromJson(json)).toList();
      return users;
    } catch (e) {
      // If the request fails, throw an exception with a message
      throw Exception('Failed to load users');
    }
  }
}

class Log extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    debugPrint('Request [${options.method}] -> Path name: ${options.path}');
    return super.onRequest(options, handler);
  }

  @override
  void onResponse(
      Response<dynamic> response, ResponseInterceptorHandler handler) {
    debugPrint(
        'Response [${response.statusCode}] -> Path name: ${response.requestOptions.path}');
    return super.onResponse(response, handler);
  }

  @override
  void onError(DioError err, ErrorInterceptorHandler handler) {
    debugPrint(
        'Error [${err.response?.statusCode}] -> Path name: ${err.requestOptions.path}');
    return super.onError(err, handler);
  }
}

class HomePage extends StatelessWidget {
  // final _dio = Dio();
  final _post = ApiService();

  HomePage({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Posts'),
      ),
      body: FutureBuilder<List<Post>>(
        future: _post.fetchPosts(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data!.length,
              itemBuilder: (context, index) {
                final post = snapshot.data![index];
                return ListTile(
                  title: Text(post.title),
                  subtitle: Text(post.body),
                );
              },
            );
          } else if (snapshot.hasError) {
            return const Center(
              child: Text('Error fetching posts'),
            );
          } else {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
    );
  }
}
....

Comments

Popular posts from this blog

Error Handling in Flutter - Gradle issue

How to Make a Dynamic and Trending ListView with Flutter Widgets?

Understanding API integration with Getx State management