easy_api_call 1.0.0 copy "easy_api_call: ^1.0.0" to clipboard
easy_api_call: ^1.0.0 copied to clipboard

A reusable HTTP API service with token management.

example/lib/main.dart

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

void main() {
  // One-time configuration
  ApiService().configure(
    ApiConfig(
      baseUrl: 'https://jsonplaceholder.typicode.com',
      enableLogging: true,
    ),
  );

  runApp(const CRUDApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'CRUD Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const CRUDScreen(),
    );
  }
}

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

  @override
  State<CRUDScreen> createState() => _CRUDScreenState();
}

class _CRUDScreenState extends State<CRUDScreen> {
  final List<Map<String, dynamic>> _operations = [
    {'method': 'GET', 'name': 'Fetch Posts'},
    {'method': 'POST', 'name': 'Create Post'},
    {'method': 'PUT', 'name': 'Update Post'},
    {'method': 'PATCH', 'name': 'Modify Post'},
    {'method': 'DELETE', 'name': 'Delete Post'},
  ];

  List<dynamic> _posts = [];
  String _result = '';
  bool _isLoading = false;
  String? _error;

  Future<void> _fetchPosts() async {
    final response = await ApiService().get<List<dynamic>>('/posts');
    setState(() {
      _posts = response.data ?? [];
      _result = 'Fetched ${_posts.length} posts';
    });
  }

  Future<void> _createPost() async {
    final response = await ApiService().post<dynamic>(
      '/posts',
      data: {
        'title': 'New Post',
        'body': 'This is a newly created post',
        'userId': 1,
      },
    );
    setState(() => _result = 'Created post with ID: ${response.data['id']}');
    _fetchPosts(); // Refresh the list
  }

  Future<void> _updatePost() async {
    if (_posts.isEmpty) {
      setState(() => _error = 'No posts available to update');
      return;
    }

    final postId = _posts.first['id'];
    final response = await ApiService().put<dynamic>(
      '/posts/$postId',
      data: {
        'id': postId,
        'title': 'Updated Post',
        'body': 'This post has been completely updated',
        'userId': 1,
      },
    );
    setState(() => _result = 'Updated post ID: ${response.data['id']}');
    _fetchPosts(); // Refresh the list
  }

  Future<void> _patchPost() async {
    if (_posts.isEmpty) {
      setState(() => _error = 'No posts available to modify');
      return;
    }

    final postId = _posts.first['id'];
    final response = await ApiService().patch<dynamic>(
      '/posts/$postId',
      data: {
        'title': 'Partially Updated Post',
      },
    );
    setState(() => _result = 'Patched post ID: ${response.data['id']}');
    _fetchPosts(); // Refresh the list
  }

  Future<void> _deletePost() async {
    if (_posts.isEmpty) {
      setState(() => _error = 'No posts available to delete');
      return;
    }

    final postId = _posts.first['id'];
    await ApiService().delete('/posts/$postId');
    setState(() => _result = 'Deleted post ID: $postId');
    _fetchPosts(); // Refresh the list
  }

  Future<void> _executeOperation(int index) async {
    setState(() {
      _isLoading = true;
      _error = null;
      _result = '';
    });

    try {
      switch (_operations[index]['method']) {
        case 'GET':
          await _fetchPosts();
          break;
        case 'POST':
          await _createPost();
          break;
        case 'PUT':
          await _updatePost();
          break;
        case 'PATCH':
          await _patchPost();
          break;
        case 'DELETE':
          await _deletePost();
          break;
      }
    } catch (e) {
      setState(() => _error = 'Unexpected error: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CRUD Operations')),
      body: Column(
        children: [
          if (_isLoading) const LinearProgressIndicator(),
          if (_error != null)
            Container(
              padding: const EdgeInsets.all(16),
              color: Colors.red[100],
              child: Row(
                children: [
                  const Icon(Icons.error, color: Colors.red),
                  const SizedBox(width: 8),
                  Expanded(child: Text(_error!)),
                  IconButton(
                    icon: const Icon(Icons.close),
                    onPressed: () => setState(() => _error = null),
                  ),
                ],
              ),
            ),
          Expanded(
            child: ListView.builder(
              itemCount: _posts.length,
              itemBuilder: (context, index) => ListTile(
                title: Text(_posts[index]['title'] ?? 'No title'),
                subtitle: Text('ID: ${_posts[index]['id']}'),
              ),
            ),
          ),
          Container(
            padding: const EdgeInsets.all(16),
            child: Text(_result, style: Theme.of(context).textTheme.titleMedium),
          ),
        ],
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          for (int i = 0; i < _operations.length; i++)
            Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: FloatingActionButton.extended(
                heroTag: 'btn$i',
                onPressed: () => _executeOperation(i),
                label: Text(_operations[i]['name']),
                icon: Icon(_getMethodIcon(_operations[i]['method'])),
              ),
            ),
        ],
      ),
    );
  }

  IconData _getMethodIcon(String method) {
    switch (method) {
      case 'GET': return Icons.download;
      case 'POST': return Icons.add;
      case 'PUT': return Icons.edit;
      case 'PATCH': return Icons.edit_attributes;
      case 'DELETE': return Icons.delete;
      default: return Icons.question_mark;
    }
  }
}
10
likes
160
points
14
downloads

Publisher

unverified uploader

Weekly Downloads

A reusable HTTP API service with token management.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

dio, pretty_dio_logger

More

Packages that depend on easy_api_call