š Lesson 11: Fetch Live Dataā± 35-40 minš Advanced
šÆ Objective
Build a simulated GitHub API client that fetches user profiles and repositories. Practice HTTP requests, JSON parsing, error handling, and concurrent API calls.
Requirements
Create a GitHubClient class with methods for user and repo data
Simulate API calls with realistic delays and responses
Fetch multiple users concurrently
Handle API errors (404, 403 rate limit, 500)
Display formatted user profiles and repository lists
import 'dart:async';
import 'dart:convert';
import 'dart:math';
// Step 1: Data models
class GitHubUser {
final String login;
final String name;
final String? bio;
final int publicRepos;
final int followers;
final String avatarUrl;
GitHubUser({
required this.login,
required this.name,
this.bio,
required this.publicRepos,
required this.followers,
required this.avatarUrl,
});
factory GitHubUser.fromJson(Map json) {
return GitHubUser(
login: json['login'] as String,
name: json['name'] as String? ?? json['login'] as String,
bio: json['bio'] as String?,
publicRepos: json['public_repos'] as int? ?? 0,
followers: json['followers'] as int? ?? 0,
avatarUrl: json['avatar_url'] as String? ?? '',
);
}
}
class GitHubRepo {
final String name;
final String? description;
final String language;
final int stars;
final int forks;
GitHubRepo({
required this.name,
this.description,
this.language = 'Unknown',
required this.stars,
required this.forks,
});
factory GitHubRepo.fromJson(Map json) {
return GitHubRepo(
name: json['name'] as String,
description: json['description'] as String?,
language: json['language'] as String? ?? 'Unknown',
stars: json['stargazers_count'] as int? ?? 0,
forks: json['forks_count'] as int? ?? 0,
);
}
}
// Step 2: Custom exceptions
class GitHubApiException implements Exception {
final int statusCode;
final String message;
GitHubApiException(this.statusCode, this.message);
@override
String toString() => 'GitHub API Error ($statusCode): $message';
}
class RateLimitException extends GitHubApiException {
RateLimitException() : super(403, 'API rate limit exceeded');
}
class UserNotFoundException extends GitHubApiException {
UserNotFoundException(String username) : super(404, 'User not found: $username');
}
// Step 3: Simulated GitHub client
class GitHubClient {
static const String _baseUrl = 'https://api.github.com';
final Random _random = Random();
int _requestCount = 0;
Future