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:

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: