In this section, we will learn how to fetch data from the internet in a Flutter application. This is a crucial skill for building modern, data-driven applications. We will cover the following topics:
- Introduction to HTTP Requests
- Using the
http
Package - Making GET Requests
- Making POST Requests
- Handling Responses
- Practical Example
- Exercises
- Introduction to HTTP Requests
HTTP (HyperText Transfer Protocol) is the foundation of any data exchange on the Web. It is a protocol used for fetching resources such as HTML documents. It is the basis of any data exchange on the Web and a protocol used by the World Wide Web.
- Using the
http
Package
http
PackageFlutter provides the http
package to make HTTP requests. To use this package, you need to add it to your pubspec.yaml
file.
After adding the dependency, run flutter pub get
to install the package.
- Making GET Requests
A GET request is used to request data from a specified resource. Here is how you can make a GET request using the http
package.
Example
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Fetch Data Example')), body: Center(child: FetchData()), ), ); } } class FetchData extends StatefulWidget { @override _FetchDataState createState() => _FetchDataState(); } class _FetchDataState extends State<FetchData> { String data = "Loading..."; @override void initState() { super.initState(); fetchData(); } Future<void> fetchData() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1')); if (response.statusCode == 200) { setState(() { data = json.decode(response.body)['title']; }); } else { setState(() { data = "Failed to load data"; }); } } @override Widget build(BuildContext context) { return Text(data); } }
Explanation
- Importing Packages: We import the
http
package anddart:convert
for JSON decoding. - Making the Request: We use
http.get
to make a GET request to the specified URL. - Handling the Response: If the response status code is 200 (OK), we decode the JSON and update the state. Otherwise, we display an error message.
- Making POST Requests
A POST request is used to send data to a server to create/update a resource. Here is how you can make a POST request.
Example
Future<void> postData() async { final response = await http.post( Uri.parse('https://jsonplaceholder.typicode.com/posts'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{ 'title': 'foo', 'body': 'bar', 'userId': '1', }), ); if (response.statusCode == 201) { print('Data posted successfully'); } else { print('Failed to post data'); } }
Explanation
- Making the Request: We use
http.post
to make a POST request to the specified URL. - Headers: We set the
Content-Type
header toapplication/json
. - Body: We encode the data to JSON format.
- Handling the Response: If the response status code is 201 (Created), we print a success message. Otherwise, we print an error message.
- Handling Responses
Handling responses is crucial for ensuring that your app behaves correctly based on the server's response. Always check the status code and handle errors appropriately.
Common Status Codes
Status Code | Description |
---|---|
200 | OK |
201 | Created |
400 | Bad Request |
401 | Unauthorized |
404 | Not Found |
500 | Internal Server Error |
- Practical Example
Let's create a practical example where we fetch a list of posts from an API and display them in a list.
Example
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Fetch Data Example')), body: Center(child: FetchData()), ), ); } } class FetchData extends StatefulWidget { @override _FetchDataState createState() => _FetchDataState(); } class _FetchDataState extends State<FetchData> { List<dynamic> data = []; @override void initState() { super.initState(); fetchData(); } Future<void> fetchData() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts')); if (response.statusCode == 200) { setState(() { data = json.decode(response.body); }); } else { setState(() { data = []; }); } } @override Widget build(BuildContext context) { return ListView.builder( itemCount: data.length, itemBuilder: (context, index) { return ListTile( title: Text(data[index]['title']), subtitle: Text(data[index]['body']), ); }, ); } }
Explanation
- Fetching Data: We fetch a list of posts from the API.
- Displaying Data: We use a
ListView.builder
to display the data in a list.
- Exercises
Exercise 1: Fetch and Display User Data
- Fetch user data from
https://jsonplaceholder.typicode.com/users
. - Display the user names in a list.
Solution
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Fetch User Data')), body: Center(child: FetchUserData()), ), ); } } class FetchUserData extends StatefulWidget { @override _FetchUserDataState createState() => _FetchUserDataState(); } class _FetchUserDataState extends State<FetchUserData> { List<dynamic> users = []; @override void initState() { super.initState(); fetchUserData(); } Future<void> fetchUserData() async { final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users')); if (response.statusCode == 200) { setState(() { users = json.decode(response.body); }); } else { setState(() { users = []; }); } } @override Widget build(BuildContext context) { return ListView.builder( itemCount: users.length, itemBuilder: (context, index) { return ListTile( title: Text(users[index]['name']), ); }, ); } }
Exercise 2: Post Data to an API
- Create a form to input a title and body.
- Post the data to
https://jsonplaceholder.typicode.com/posts
.
Solution
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Post Data Example')), body: Center(child: PostDataForm()), ), ); } } class PostDataForm extends StatefulWidget { @override _PostDataFormState createState() => _PostDataFormState(); } class _PostDataFormState extends State<PostDataForm> { final _formKey = GlobalKey<FormState>(); String title = ''; String body = ''; Future<void> postData() async { final response = await http.post( Uri.parse('https://jsonplaceholder.typicode.com/posts'), headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode(<String, String>{ 'title': title, 'body': body, 'userId': '1', }), ); if (response.statusCode == 201) { print('Data posted successfully'); } else { print('Failed to post data'); } } @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( children: <Widget>[ TextFormField( decoration: InputDecoration(labelText: 'Title'), onSaved: (value) { title = value!; }, ), TextFormField( decoration: InputDecoration(labelText: 'Body'), onSaved: (value) { body = value!; }, ), ElevatedButton( onPressed: () { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); postData(); } }, child: Text('Submit'), ), ], ), ); } }
Conclusion
In this section, we learned how to fetch data from the internet using the http
package in Flutter. We covered making GET and POST requests, handling responses, and implemented practical examples. We also provided exercises to reinforce the learned concepts. In the next section, we will learn how to parse JSON data.
Flutter Development Course
Module 1: Introduction to Flutter
- What is Flutter?
- Setting Up the Development Environment
- Understanding Flutter Architecture
- Creating Your First Flutter App
Module 2: Dart Programming Basics
- Introduction to Dart
- Variables and Data Types
- Control Flow Statements
- Functions and Methods
- Object-Oriented Programming in Dart
Module 3: Flutter Widgets
- Introduction to Widgets
- Stateless vs Stateful Widgets
- Basic Widgets
- Layout Widgets
- Input and Form Widgets
Module 4: State Management
Module 5: Navigation and Routing
Module 6: Networking and APIs
- Fetching Data from the Internet
- Parsing JSON Data
- Handling Network Errors
- Using REST APIs
- GraphQL Integration
Module 7: Persistence and Storage
- Introduction to Persistence
- Shared Preferences
- File Storage
- SQLite Database
- Using Hive for Local Storage
Module 8: Advanced Flutter Concepts
- Animations in Flutter
- Custom Paint and Canvas
- Platform Channels
- Isolates and Concurrency
- Performance Optimization
Module 9: Testing and Debugging
Module 10: Deployment and Maintenance
- Preparing for Release
- Building for iOS
- Building for Android
- Continuous Integration/Continuous Deployment (CI/CD)
- Maintaining and Updating Your App