Flutter Avoiding Jank (original) (raw)
Last Updated : 07 Mar, 2025
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> 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> through the below steps:
- Make a Photos_parser() function to convert the response body into a List.
- Use the Photos_parser() function in the getPhotos() function. Dart `
List Photos_parser(String responseBody) { final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>(); return parsed.map((json) => Photo.fromJson(json)).toList(); }
Future<List> 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> 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> 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 Photos_parser(String responseBody) { final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>(); return parsed.map((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>( 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 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: