Fetching Data from an API in a Flutter Splash Screen and Inserting it into a Database

Flutter is a popular framework for developing cross-platform mobile applications. In the following article, we'll look at a simple Flutter app featuring a splash screen. We'll read via the given code to understand its structure and purpose.
Imports: The code begins by importing two packages:
flutter/material.dartand a customsplash_screen.dartfile. These imports are essential for building the user interface and managing navigation within the app.main()Function: Themain()function is the entry point of a Flutter app. Here, it ensures that Flutter is initialized and then runs theMyAppwidget.MyAppWidget:MyAppis a custom Flutter widget that extendsStatelessWidget. In Flutter, everything is a widget, and widgets are the building blocks of your app's UI.build()Method: Thebuild()method is where you define the structure of your app. Here's what's happening within this method:MaterialApp: It's a Flutter widget that provides a Material Design-themed app. ThedebugShowCheckedModeBannerproperty is set tofalseto hide the debug banner when running the app in debug mode.title: This sets the title of the app to 'REST API'.home: Thehomeproperty specifies the initial screen of the app, and it's set toSplashScreenPage(). This suggests that your app starts with a splash screen, andSplashScreenPagelikely resides in thesplash_screen.dartfile you've imported.
import 'package:flutter/material.dart';
import 'package:rest_api/splash_screen.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'REST API',
home: SplashScreenPage(),
);
}
}
Splash Screen and Beyond
In this code, you've set up the foundation for your Flutter app. It begins with a splash screen, and from there, you can expand and create additional screens and functionality.
To implement the splash screen, you can customize the
SplashScreenPagein thesplash_screen.dartfile. A splash screen is often used to display a logo or branding while the app loads resources.As your app evolves, you can navigate to other screens, fetch data from REST APIs, and provide a rich user experience. Flutter offers various packages and tools for making HTTP requests, handling responses, and managing state.
Creating a Flutter Model Class: PhotoModel
In Flutter, model classes are crucial for representing data structures that your application uses. In this article, we'll explore the PhotoModel class you've provided. This class is designed to represent photo data fetched from an API and serves as a blueprint for how this data is structured in this Flutter app.
Understanding the PhotoModel Class
class PhotoModel {
int? albumId;
int? id;
String? title;
String? url;
String? thumbnailUrl;
PhotoModel({this.albumId, this.id, this.title, this.url, this.thumbnailUrl});
PhotoModel.fromJson(Map<String, dynamic> json) {
albumId = json['albumId'];
id = json['id'];
title = json['title'];
url = json['url'];
thumbnailUrl = json['thumbnailUrl'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['albumId'] = albumId;
data['id'] = id;
data['title'] = title;
data['url'] = url;
data['thumbnailUrl'] = thumbnailUrl;
return data;
}
}
Properties: The PhotoModel class defines several properties that represent attributes of a photo object:
albumId: An integer representing the album to which the photo belongs.id: An integer uniquely identifying the photo.title: A string describing the title or caption of the photo.url: A string containing the URL where the full-sized photo can be accessed.thumbnailUrl: A string with the URL of a thumbnail version of the photo.
Constructor: This is a constructor method for the PhotoModel class. It allows you to create instances of PhotoModel with optional named parameters. This means you can create a PhotoModel object with any combination of properties.
fromJson Factory Method: This method is used to create a PhotoModel object from a JSON map (a key-value pair structure commonly used for data interchange). It takes a Map<String, dynamic> as input, extracts the values for each property from the map, and assigns them to the corresponding class properties.
toJson Method: This method converts a PhotoModel object back into a JSON map. It creates a new map, assigns each property's value to the corresponding key, and returns the map as a JSON representation of the object.
Managing Local Database in a Flutter App: DatabaseHelper Class
In this page, we'll explore the DatabaseHelper class you've provided. This class is a critical component of your Flutter app as it handles the initialization and management of a local SQLite database. This database is used to store and retrieve instances of the PhotoModel class, which represents photo data fetched from a remote API.
import 'package:rest_api/model/photomodel.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
Future<Database> initializedDB() async {
String path = await getDatabasesPath();
return openDatabase(
join(path,'photos.db'),
version: 1,
onCreate: (Database db, int version) async{
await db.execute(
"CREATE TABLE photos("
"albumId INTEGER,"
" id INTEGER PRIMARY KEY,"
" title TEXT NOT NULL,"
" url TEXT NOT NULL,"
" thumbnailUrl TEXT NOT NULL)"
);
}
);
}
Future<int> insertData (PhotoModel data) async {
final db = await initializedDB();
return await db.insert('photos', data.toJson(),
conflictAlgorithm: ConflictAlgorithm.replace); }
Future<List<PhotoModel>> getAllData() async{
final db = await initializedDB();
final List<Map<String,dynamic>> maps = await db.query('photos');
return List.generate(maps.length, (i){
return PhotoModel.fromJson(maps[i]);
});
}
}
Imports: The class imports necessary packages like photomodel.dart for working with PhotoModel objects, sqflite for SQLite database operations, and path for managing file paths.
initializedDB Method: This method is responsible for initializing the SQLite database. It returns a Future<Database>, which represents the database instance. Here's what this method does:
It determines the path where the database file should be stored using
getDatabasesPath().It opens or creates a new SQLite database named
photos.dbat the specified path.If the database doesn't exist, the
onCreatecallback is executed. In this callback, it defines the structure of thephotostable with columns foralbumId,id,title,url, andthumbnailUrl.
insertData Method: This method inserts a PhotoModel object (data) into the photos table. It returns the ID of the newly inserted row as a Future<int>. Key points:
It retrieves a reference to the initialized database.
It uses the
insertmethod to add the data to thephotostable. TheconflictAlgorithm: ConflictAlgorithm.replaceparameter specifies that if there is a conflict (i.e., a row with the same primary key exists), it should replace the existing row.
getAllData Method: This method retrieves all data from the photos table and returns it as a list of PhotoModel objects. Here's how it works:
It retrieves a reference to the initialized database.
It uses the
querymethod to fetch all rows from thephotostable, resulting in a list ofMap<String, dynamic>objects.It uses
List.generateto convert each map into aPhotoModelobject by calling thePhotoModel.fromJsonconstructor.
Creating a Splash Screen in Flutter with Data Fetching and Local Database
In this page, we'll explore a Flutter SplashScreenPage class that serves as an introductory screen for this app. This splash screen is designed to fetch data from a remote API, store it in a local database, and then navigate to another page while displaying an image. Let's dive into the code :
import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:rest_api/photo.dart';
import 'datahelper.dart';
import 'model/photomodel.dart';
class SplashScreenPage extends StatefulWidget {
const SplashScreenPage({super.key});
@override
State<SplashScreenPage> createState() => _SplashScreenPageState();
}
class _SplashScreenPageState extends State<SplashScreenPage> {
final dbHelper = DatabaseHelper();
late final List<PhotoModel> data = [];
@override
void initState() {
databaseInitialized();
fetchAndSavePhotos();
super.initState();
}
Future<void> databaseInitialized() async {
await dbHelper.initializedDB();
}
Future fetchAndSavePhotos() async {
final response = await http
.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1/photos'));
if (response.statusCode == 200) {
var jsonData = json.decode(response.body);
final dbHelper = DatabaseHelper();
for (final item in jsonData) {
PhotoModel yourData = PhotoModel.fromJson(item);
await dbHelper.insertData(yourData);
}
data.clear();
data.addAll(await dbHelper.getAllData());
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => MyHomePage(data : data )),
);
} else {
throw Exception('Failed to local data from the API');
}
return data;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
top: true,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 1,
color: Colors.black,
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
'https://wallpapercave.com/wp/wp5443115.jpg',
fit: BoxFit.scaleDown,
),
),
),
),
),
);
}
}
Imports: The code imports essential packages, including flutter/material.dart for Flutter UI, http for making HTTP requests, and custom files like datahelper.dart and model/photomodel.dart, which contain database and data model logic.
State Class: _SplashScreenPageState is the state class for your SplashScreenPage. It contains the logic for fetching and managing data, as well as a list to store photo data.
initState Method: In the initState method, you perform the following actions:
Call
databaseInitializedto initialize the local database usingDatabaseHelper.Call
fetchAndSavePhotosto fetch data from a remote API and save it to the local database.
databaseInitializedMethod: This method initializes the local database using theDatabaseHelperclass. It awaits the completion of the database initialization.fetchAndSavePhotosMethod: This asynchronous method fetches data from a remote API and saves it to the local database:It makes an HTTP GET request to the API using the
httppackage.If the response status code is 200 (indicating success), it decodes the JSON response and saves each item to the database using
dbHelper.insertData.After saving the data, it clears and populates the
datalist with the data from the database.Finally, it navigates to another page (
MyHomePage) while passing the fetched data.
buildMethod: Thebuildmethod defines the UI structure of your splash screen. In this case, it displays a black background with a centered image fetched from a URL. This screen will be shown while data is fetched and processed.
Building a Flutter Photo List Page
In this page, we'll explore a Flutter MyHomePage class, which represents a photo list page that displays a list of photos fetched from a local database. Users can tap on a photo to view its details. Let's dissect the code :
import 'package:flutter/material.dart';
import 'package:rest_api/datahelper.dart';
import 'package:rest_api/details.dart';
import 'package:rest_api/model/photomodel.dart';
class MyHomePage extends StatefulWidget {
final List<PhotoModel> data;
const MyHomePage({Key? key, required this.data}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final dbHelper = DatabaseHelper();
bool isLoading = true;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('REST API'),
),
body: ListView.builder(
itemCount: widget.data.length,
itemBuilder: (context, index) {
return SizedBox(
height: 100,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DetailsPage( photoModel: widget.data[index],),
),
);
},
child: Card(
elevation: 4,
child: Row(
children: [
Image.network(widget.data[index].url.toString(),
width: 80, fit: BoxFit.cover),
Expanded(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.data[index].id.toString(),
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold),
),
Text(
widget.data[index].title.toString(),
maxLines: 2,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold),
),
Text(
widget.data[index].thumbnailUrl.toString(),
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400),
),
],
),
))
],
),
),
),
);
},
),
);
}
}
Imports: The code includes necessary imports for Flutter (flutter/material.dart) and custom classes like datahelper.dart, details.dart, and model/photomodel.dart. MyHomePage receives a list of PhotoModel objects as its data source.
State Class: _MyHomePageState is the state class for your MyHomePage. It manages the state of the widget.
build Method: The build method defines the UI structure of your MyHomePage widget. Here's how it works:
It creates a
Scaffoldwith anAppBarat the top, displaying the title "REST API."The body of the
Scaffoldis aListView.builderwidget that generates a list of photo items using the data received from the constructor.For each photo item, it creates a
Cardwith anImageand additional details.The
GestureDetectorallows users to tap on a photo, triggering navigation to theDetailsPagewhile passing the selectedPhotoModel.
Creating a Flutter Details Page for Photo Display
In this page, we'll explore a Flutter DetailsPage class that is responsible for displaying detailed information about a specific photo. This page will show the photo, its ID, title, and thumbnail URL. Let's break down the code :
import 'package:flutter/material.dart';
import 'package:rest_api/model/photomodel.dart';
class DetailsPage extends StatelessWidget {
final PhotoModel photoModel;
const DetailsPage({Key? key, required this.photoModel}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Details'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 10,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Card(
margin: EdgeInsets.only(top: 30),
elevation: 10,
child: Image.network(
photoModel.url.toString(),
width: 300,
height: 200,
fit: BoxFit.cover,
),
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
photoModel.id.toString(),
style: TextStyle(fontSize: 21, fontWeight: FontWeight.bold),
),
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
photoModel.title.toString(),
style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold),
),
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
photoModel.thumbnailUrl.toString(),
style: TextStyle(fontSize: 16,fontWeight: FontWeight.w400),
),
),
],
),
),
),
);
}
}
Here's a breakdown of the DetailsPage code:
Imports: The code includes necessary imports for Flutter (
flutter/material.dart) andPhotoModelfor displaying the details of the selected photo.Constructor: The
DetailsPageclass has a constructor that takes aPhotoModelobject as a parameter. This allows you to pass the specific photo's data to the details page when navigating to it.buildMethod: This method defines the UI structure of theDetailsPagewidget. Here's how it works:It creates a
Scaffoldwith anAppBarthat displays the title "Details."Inside the
Scaffold, there's aCardwidget with elevated content for displaying the photo details.The photo is displayed in the center using an
Image.networkwidget. The image URL is obtained from thephotoModel.Below the photo, there are three pieces of information displayed: ID, title, and thumbnail URL. Each piece of information is placed in a
Textwidget with different text styles.The
SizedBoxwidgets add vertical spacing between the elements for better readability.
Setting up a Flutter Project with REST API Integration
In this article, we will guide you through setting up a Flutter project named "rest_api" for integrating REST API data fetching and displaying it in your app. We'll also include dependencies for HTTP requests, local database storage, and splash screen functionality.
Here's your
pubspec.yamlfile with the necessary configurations and dependencies:name: rest_api description: A new Flutter project. publish_to: 'none' version: 1.0.0+1 environment: sdk: '>=3.0.5 <4.0.0' dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 http: ^1.1.0 # For making HTTP requests to your API sqflite: ^2.3.0 # For local database storage path: ^1.8.3 # For handling file paths splash_screen_view: ^3.0.0 # For implementing a splash screen dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 # Optional linting rules for your Flutter project flutter: uses-material-design: true




