DEV Community

ldFlutter
ldFlutter

Posted on

Api Structure with Http

  1. Dealing with asynchronously
    Note that the HTTP APIs use Dart Futures in the return values. We recommend using the API calls with the async/await syntax.

  2. Create the client.

  3. Construct the Uri.

  4. Invoke the operation, and await the request object. Optionally, configure the headers and body of the request.

  5. Close the request, and await the response.

  6. Decode the response.

Several of these steps use Future based APIs. Sample APIs calls for each step above are:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'user_model.dart';

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

  /// GET - List of Users
  static Future<List<UserModel>> getUsers() async {
    final response = await http.get(Uri.parse('$baseUrl/users'));

    if (response.statusCode == 200) {
      List data = jsonDecode(response.body);

      // List<Map> -> List<Model>
      return data.map((e) => UserModel.fromJson(e)).toList();
    } else {
      throw Exception('Failed to load users');
    }
  }

  /// GET - Single User
  static Future<UserModel> getUser(int id) async {
    final response = await http.get(Uri.parse('$baseUrl/users/$id'));

    if (response.statusCode == 200) {
      Map<String, dynamic> data = jsonDecode(response.body);

      return UserModel.fromJson(data);
    } else {
      throw Exception('Failed to load user');
    }
  }

  /// POST - Create User
  static Future<UserModel> createUser(UserModel user) async {
    final response = await http.post(
      Uri.parse('$baseUrl/users'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode(user.toJson()),
    );

    if (response.statusCode == 201) {
      Map<String, dynamic> data = jsonDecode(response.body);

      return UserModel.fromJson(data);
    } else {
      throw Exception('Failed to create user');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Model Class (User Model) Example JSON:
class UserModel {
  final int id;
  final String name;
  final String email;

  UserModel({
    required this.id,
    required this.name,
    required this.email,
  });

  // From JSON (Map -> Model)
  factory UserModel.fromJson(Map<String, dynamic> json) {
    return UserModel(
      id: json['id'] ?? 0,
      name: json['name'] ?? '',
      email: json['email'] ?? '',
    );
  }

  // To JSON (Model -> Map)
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
    };
  }
}

Enter fullscreen mode Exit fullscreen mode
  1. Simple UI Example main.dart
import 'package:flutter/material.dart';
import 'api_service.dart';
import 'user_model.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: UserScreen(),
    );
  }
}

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

  @override
  State<UserScreen> createState() => _UserScreenState();
}

class _UserScreenState extends State<UserScreen> {
  List<UserModel> users = [];
  bool isLoading = false;

  @override
  void initState() {
    super.initState();
    fetchUsers();
  }

  Future<void> fetchUsers() async {
    setState(() => isLoading = true);

    try {
      users = await ApiService.getUsers();
    } catch (e) {
      print(e);
    }

    setState(() => isLoading = false);
  }

  Future<void> addUser() async {
    UserModel newUser = UserModel(
      id: 0,
      name: "Devik",
      email: "devik@test.com",
    );

    try {
      UserModel createdUser = await ApiService.createUser(newUser);

      setState(() {
        users.add(createdUser);
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("API Demo")),
      body: isLoading
          ? const Center(child: CircularProgressIndicator())
          : ListView.builder(
              itemCount: users.length,
              itemBuilder: (context, index) {
                final user = users[index];

                return ListTile(
                  title: Text(user.name),
                  subtitle: Text(user.email),
                );
              },
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: addUser,
        child: const Icon(Icons.add),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)