Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.

Learn more

Flutter 3.41 is live! Check out theFlutter 3.41 blog post!

Parse JSON in the background

How to perform a task in the background.

By default, Dart apps do all of their work on a single thread. In many cases, this model simplifies coding and is fast enough that it does not result in poor app performance or stuttering animations, often called "jank."

However, you might need to perform an expensive computation, such as parsing a very large JSON document. If this work takes more than 16 milliseconds, your users experience jank.

To avoid jank, you need to perform expensive computations like this in the background, using a separateIsolate. This recipe uses the following steps:

  1. Add thehttp package.
  2. Make a network request using thehttp package.
  3. Convert the response into a list of photos.
  4. Move this work to a separate isolate.

1. Add thehttp package

#

First, add thehttp package to your project. Thehttp package makes it easier to perform network requests, such as fetching data from a JSON endpoint.

To add thehttp package as a dependency, runflutter pub add:

flutter pub add http

2. Make a network request

#

This example covers how to fetch a large JSON document that contains a list of 5000 photo objects from theJSONPlaceholder REST API, using thehttp.get() method.

dart
Future<http.Response>fetchPhotos(http.Clientclient)async{returnclient.get(Uri.parse('https://jsonplaceholder.typicode.com/photos'));}
Note

You're providing anhttp.Client to the function in this example. This makes the function easier to test and use in different environments.

Next, following the guidance from theFetch data from the internet recipe, convert thehttp.Response into a list of Dart objects. This makes the data easier to work with.

Create aPhoto class

#

First, create aPhoto class that contains data about a photo. Include afromJson() factory method to make it easy to create aPhoto starting with a JSON object.

dart
classPhoto{finalintalbumId;finalintid;finalStringtitle;finalStringurl;finalStringthumbnailUrl;constPhoto({requiredthis.albumId,requiredthis.id,requiredthis.title,requiredthis.url,requiredthis.thumbnailUrl,});factoryPhoto.fromJson(Map<String,dynamic>json){returnPhoto(albumId:json['albumId']asint,id:json['id']asint,title:json['title']asString,url:json['url']asString,thumbnailUrl:json['thumbnailUrl']asString,);}}

Convert the response into a list of photos

#

Now, use the following instructions to update thefetchPhotos() function so that it returns aFuture<List<Photo>>:

  1. Create aparsePhotos() function that converts the response body into aList<Photo>.
  2. Use theparsePhotos() function in thefetchPhotos() function.
dart
// A function that converts a response body into a List<Photo>.List<Photo>parsePhotos(StringresponseBody){finalparsed=(jsonDecode(responseBody)asList<Object?>).cast<Map<String,Object?>>();returnparsed.map<Photo>(Photo.fromJson).toList();}Future<List<Photo>>fetchPhotos(http.Clientclient)async{finalresponse=awaitclient.get(Uri.parse('https://jsonplaceholder.typicode.com/photos'),);// Synchronously run parsePhotos in the main isolate.returnparsePhotos(response.body);}

4. Move this work to a separate isolate

#

If you run thefetchPhotos() function on a slower device, you might notice the app freezes for a brief moment as it parses and converts the JSON. This is jank, and you want to get rid of it.

You can remove the jank by moving the parsing and conversion to a background isolate using thecompute() function provided by Flutter. Thecompute() function runs expensive functions in a background isolate and returns the result. In this case, run theparsePhotos() function in the background.

dart
Future<List<Photo>>fetchPhotos(http.Clientclient)async{finalresponse=awaitclient.get(Uri.parse('https://jsonplaceholder.typicode.com/photos'),);// Use the compute function to run parsePhotos in a separate isolate.returncompute(parsePhotos,response.body);}

Notes on working with isolates

#

Isolates communicate by passing messages back and forth. These messages can be primitive values, such asnull,num,bool,double, orString, or simple objects such as theList<Photo> in this example.

You might experience errors if you try to pass more complex objects, such as aFuture orhttp.Response between isolates.

As an alternate solution, check out theworker_manager orworkmanager packages for background processing.

Complete example

#
dart
import'dart:async';import'dart:convert';import'package:flutter/foundation.dart';import'package:flutter/material.dart';import'package:http/http.dart'ashttp;Future<List<Photo>>fetchPhotos(http.Clientclient)async{finalresponse=awaitclient.get(Uri.parse('https://jsonplaceholder.typicode.com/photos'),);// Use the compute function to run parsePhotos in a separate isolate.returncompute(parsePhotos,response.body);}// A function that converts a response body into a List<Photo>.List<Photo>parsePhotos(StringresponseBody){finalparsed=(jsonDecode(responseBody)asList<Object?>).cast<Map<String,Object?>>();returnparsed.map<Photo>(Photo.fromJson).toList();}classPhoto{finalintalbumId;finalintid;finalStringtitle;finalStringurl;finalStringthumbnailUrl;constPhoto({requiredthis.albumId,requiredthis.id,requiredthis.title,requiredthis.url,requiredthis.thumbnailUrl,});factoryPhoto.fromJson(Map<String,dynamic>json){returnPhoto(albumId:json['albumId']asint,id:json['id']asint,title:json['title']asString,url:json['url']asString,thumbnailUrl:json['thumbnailUrl']asString,);}}voidmain()=>runApp(constMyApp());classMyAppextendsStatelessWidget{constMyApp({super.key});@overrideWidgetbuild(BuildContextcontext){constappTitle='Isolate Demo';returnconstMaterialApp(title:appTitle,home:MyHomePage(title:appTitle),);}}classMyHomePageextendsStatefulWidget{constMyHomePage({super.key,requiredthis.title});finalStringtitle;@overrideState<MyHomePage>createState()=>_MyHomePageState();}class_MyHomePageStateextendsState<MyHomePage>{lateFuture<List<Photo>>futurePhotos;@overridevoidinitState(){super.initState();futurePhotos=fetchPhotos(http.Client());}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text(widget.title)),body:FutureBuilder<List<Photo>>(future:futurePhotos,builder:(context,snapshot){if(snapshot.hasError){returnconstCenter(child:Text('An error has occurred!'));}elseif(snapshot.hasData){returnPhotosList(photos:snapshot.data!);}else{returnconstCenter(child:CircularProgressIndicator());}},),);}}classPhotosListextendsStatelessWidget{constPhotosList({super.key,requiredthis.photos});finalList<Photo>photos;@overrideWidgetbuild(BuildContextcontext){returnGridView.builder(gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2,),itemCount:photos.length,itemBuilder:(context,index){returnImage.network(photos[index].thumbnailUrl);},);}}

Isolate demo

Was this page's content helpful?

Unless stated otherwise, the documentation on this site reflects Flutter 3.38.6. Page last updated on 2025-08-19.View source orreport an issue.


[8]ページ先頭

©2009-2026 Movatter.jp