Skip to content

Instantly share code, notes, and snippets.

@bwnyasse
Last active November 12, 2023 16:44
Show Gist options
  • Save bwnyasse/c131ae5d7f74439d15119826ff635906 to your computer and use it in GitHub Desktop.
Save bwnyasse/c131ae5d7f74439d15119826ff635906 to your computer and use it in GitHub Desktop.
/*
* Dart & Flutter - Training
* Workshop: Advanced Dart Programming - HTTP Requests, Streams, and Mixins
* Copyright (Boris-Wilfried Nyasse)
* All rights reserved
*
* Workshop Goals and Objectives:
* - Implement HTTP requests to fetch data from an external API.
* - Use mixins for data formatting.
* - Understand and utilize streams for asynchronous data processing.
* - Apply advanced Dart features in a real-world scenario.
*
* In this workshop, you'll build a program that fetches movie data from an API
* and processes it using Dart's advanced features like HTTP requests, streams, and mixins.
*
* Follow the FIXMEs and TODOs to complete the workshop.
*/
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
// Mixin for formatting movie data.
mixin MovieFormatter {
// Formats the movie data into a readable string.
String formatMovieData(
String title,
String releaseDate,
double popularity,
) {
return '''Movie:
$title
Release Date: $releaseDate
Popularity: $popularity''';
}
}
// Movie class
class Movie {
String title;
String releaseDate;
double popularity;
// Constructor with optional named parameters for movie properties.
Movie({
this.title = 'Unknown',
this.releaseDate = 'N/A',
this.popularity = 0.0,
});
// Overridden toString method using the formatMovieData function from the mixin.
@override
String toString() {
// FIXME: 1- Ensure the Movie class correctly implements the MovieFormatter mixin to use the formatMovieData method.
return formatMovieData(title, releaseDate, popularity);
}
}
// Fetches the first movie from the API and returns a Movie object.
Future<Movie> fetchFirstMovie() async {
const apiKey = '4205ec1d93b1e3465f636f0956a98c64';
const api = 'https://api.themoviedb.org/3';
const urlPath = 'movie/now_playing';
final url = Uri.parse('$api/$urlPath?api_key=$apiKey&language=en-US');
try {
final response = http.get(url);
// FIXME: 2- Modify the http.get(url) call to properly handle the asynchronous HTTP request and fetch the response.
if (response.statusCode == 200) {
var data = json.decode(response.body);
var firstMovieData = data['results'][0];
return Movie(
title: firstMovieData['title'] ?? 'No title',
releaseDate: firstMovieData['release_date'] ?? 'No release date',
popularity: firstMovieData['popularity'] ?? 0.0,
);
} else {
print('Request failed with status: ${response.statusCode}.');
return Movie();
}
} catch (e) {
print("Error fetching movie: $e");
return Movie();
}
}
// Stream of movies, simulating asynchronous fetching of movies.
// FIXME: 3- Update the movieStream function's signature to accurately represent it as an asynchronous stream generator.
Stream<Movie> movieStream() async {
for (int i = 0; i < 5; i++) {
await Future.delayed(const Duration(seconds: 1));
yield await fetchFirstMovie();
}
}
// Main function to run the workshop code.
void main() async {
print('Starting movie stream...');
// TODO: 4- Write a loop in the main function to iterate over the movieStream and print details for each movie.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment