Parsing large JSON files can lead to poor performance of apps and shuttering animations. If parsing and computing a large JSON file take more than 16 milliseconds, the users will experience Jank. Dart by default uses a single thread to perform these tasks, though being simple and fast for less expensive computation, it fails when the computation in large.
To avoid these janks, isolates can be used to perform all computations in a different thread in the background. In this article, we will explore the process of parsing JSON in the background.
Steps to implement Avoiding Jank in Flutter
Step 1 : Create a new flutter application
Create a new Flutter application using command Prompt. For creating a new app, write flutter create YOUR_APP_NAME and run this command.
flutter create jank_flutter
To know more about it refer this article: Creating a Simple Application in Flutter
Step 2 : Adding the Dependency
To add the dependency to the pubspec.yaml file, add shimmer as a dependency in the dependencies part of the pubspec.yaml file as shown below:
dependencies:
http: ^1.3.0
Now run the below command in terminal.
flutter pub get
Step 3 : Importing the Dependency
Use the below line of code in the main.dart file, to import the shimmer dependency :
import 'package:http/http.dart' as http;
Step 4 : Requesting Data
We can use the http.get() method to fetch the sample data of 5000 images from JSONPlaceholder REST API as shown below:
Dart
Future<List<Photo>> fetchPhotos(http.Client client) async {
final response = await client.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1/photos'),
);
return response;
}
Step 5 : Parsing and Converting the Data
We now have 50 photos in JSON form received from the http.response and these need to be parsed and converted into a list of Dart objects. To do show First create a Photo class as shown below.
Here we will create a Photo class that contains the JSON data as shown below:
Dart
class Photo {
final int photo_id;
final String photo_title;
final String photo_thumbnailUrl;
Photo({
required this.photo_id,
required this.photo_title,
required this.photo_thumbnailUrl,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
photo_id: json['id'] as int,
photo_title: json['title'] as String,
// Option 1: Use the original thumbnailUrl (may not load as expected)
// photo_thumbnailUrl: json['thumbnailUrl'] as String,
// Option 2: Generate a new URL from Picsum using the photo id as a seed.
photo_thumbnailUrl: 'https://picsum.photos/seed/${json['id']}/150/150',
);
}
}
Now update the getPhoto() function to returns a Future<List<Photo>> through the below steps:
- Make a Photos_parser() function to convert the response body into a List<Photo>.
- Use the Photos_parser() function in the getPhotos() function.
Dart
List<Photo> Photos_parser(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();
}
Future<List<Photo>> getPhotos(http.Client client) async {
final response = await client.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1/photos'),
);
// Run Photos_parser in a separate isolate.
return compute(Photos_parser, response.body);
}
Step 6 : Moving work to a different Isolate.
The compute() function can be used to move the work to a separate isolate where it will be parsed and converted in the background. It runs expensive functions in a background isolate and returns the result.
Dart
Future<List<Photo>> getPhotos(http.Client client) async {
final response = await client.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1/photos'),
);
// Run Photos_parser in a separate isolate.
return compute(Photos_parser, response.body);
}
Complete Source Code
main.dart:
Dart
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Photo>> getPhotos(http.Client client) async {
final response = await client.get(
Uri.parse('https://jsonplaceholder.typicode.com/albums/1/photos'),
);
// Run Photos_parser in a separate isolate.
return compute(Photos_parser, response.body);
}
List<Photo> Photos_parser(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final appTitle = 'geeksforgeeks';
return MaterialApp(
title: appTitle,
debugShowCheckedModeBanner: false,
home: HomePage(title: appTitle),
);
}
}
class HomePage extends StatelessWidget {
final String title;
HomePage({super.key, required this.title});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
title: Text(title),
),
body: FutureBuilder<List<Photo>>(
future: getPhotos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? PhotosList(photos: snapshot.data!)
: Center(child: CircularProgressIndicator());
},
),
);
}
}
class PhotosList extends StatelessWidget {
final List<Photo> photos;
PhotosList({super.key, required this.photos});
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: photos.length,
itemBuilder: (context, index) {
return Image.network(photos[index].photo_thumbnailUrl);
},
);
}
}
class Photo {
final int photo_id;
final String photo_title;
final String photo_thumbnailUrl;
Photo({
required this.photo_id,
required this.photo_title,
required this.photo_thumbnailUrl,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
photo_id: json['id'] as int,
photo_title: json['title'] as String,
// Option 1: Use the original thumbnailUrl (may not load as expected)
// photo_thumbnailUrl: json['thumbnailUrl'] as String,
// Option 2: Generate a new URL from Picsum using the photo id as a seed.
photo_thumbnailUrl: 'https://picsum.photos/seed/${json['id']}/150/150',
);
}
}
To know more about GridView in flutter refer this article: Flutter – GridView
Output:
Similar Reads
Floating SnackBar in Flutter The floating_snackbar in Flutter is used to display a temporary message to users, often as feedback after an action.We know how to show the snack bar in a flutter, but everybody wants the application must look more interactive and user-friendly, that's why we can use animations or new designs in the
3 min read
Flutter - Building News Reader App In today's fast-paced world, staying informed is essential, and mobile applications have become a popular medium for accessing news. In this article, we'll guide you through building a News Reader App step by step using Flutter, a powerful and versatile framework for creating cross-platform applicat
5 min read
BLoC Pattern Flutter In Flutter applications, the Flutter BLoC (Business Logic Component) is used to manage the state. It helps separate business logic from UI. It ensures that the user interface is not strongly liaison with the business logic, making the app more versatile. It is powerful since it allows the creation o
10 min read
Flutter - KF Drawer In many Android Applications, you may see Sidebar which has some items that perform some tasks like showing the profile UI, and displaying the About us page, In the application world it is called Drawer. Drawer is the side navigation bar that is used to access the different pages of the Application.
4 min read
Flutter - Building a Tic Tac Toe Game Flutter SDK is an open-source software development kit for building beautiful UI that is natively compiled. In this article, we will build a Tic Tac Toe. Tic Tac Toe is a two-player game played on a 3x3 grid. One player uses "X" and the other "O." The goal is to be the first to get three of your sym
11 min read