Implementing Pull-To-Refresh In Flutter
In this blog, we shall discuss about Pull-To-Refresh feature. Most of the apps that are made today come with API integration, sometimes when there is a change in data of the API the change might not change in realtime in the app so we need to load the data again in our app. Flutter provides us RefreshIndicator widget that can be used to implement the same feature.
RefreshIndicator is a widget that provides us onRefresh
a property that we can use for reloading the API data. When the refresh operation is finished it returns a future.
Table of content
Fetching JSON data
- Here we have created a function
fetchFruit()
that will fetch the JSON data from the given URL.
Future fetchFruit() async {
final response = await http.get('url');
if (response.statusCode == 200) {
//decode_JSON_data
} else {
throw Exception('Unable to fetch data from the REST API');
}
}
Decode data
- We can use the decode method to decode the
responseBody
and then we can map theparsed
to list.
List<Fruit> decodeFruit(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Fruit>((json) => Fruit.fromMap(json)).toList();
}
Fruit Class
class Fruit {
final int id;
final String title;
final String imageUrl;
final int quantity;
Fruit(
this.id,
this.title,
this.imageUrl,
this.quantity,
);
factory Fruit.fromMap(Map<String, dynamic> json) {
return Fruit(json['id'], json['title'], json['imageUrl'], json['quantity']);
}
factory Fruit.fromJson(Map<String, dynamic> json) {
return Fruit(json['id'], json['title'], json['imageUrl'], json['quantity']);
}
}
Creating MyApp class
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:rest_api_flutter/fruitItem.dart';
import 'dart:async';
import 'fruit.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp(products: fetchFruit()));
class MyApp extends StatelessWidget {
final Future<List<Fruit>> products;
MyApp({this.products});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyHomePage(products: products),
);
}
}
Displaying API data
- To display the
future
data we need to useFutureBuilder
that takes a future and a builder to display the data. Here theproducts
future contains the API data so we need to use the FutureBuilder to display the data.ListView.builder
widget can be used to create the list of API data.
FutureBuilder<List<Fruit>>(
future: products,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return FruitItem(item: snapshot.data[index]);
},
)
: Center(child: CircularProgressIndicator());
},
),
Using RefreshIndicator
- To refresh the future data we need to use the
RefreshIndicator
widget that provides usonRefresh
property that takes the future and it reloads the whole future whenever it is called.
RefreshIndicator(
onRefresh: () => _refreshProducts(context),
child: FutureBuilder<List<Fruit>>(
future: products,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return FruitItem(item: snapshot.data[index]);
},
)
: Center(child: CircularProgressIndicator());
},
),
),
Refresh function
This is used inside the RefreshIndicator to reload the API data.
Future<void> _refreshProducts(BuildContext context) async {
return fetchFruit();
}
Have a look at the main dart file :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:rest_api_flutter/fruitItem.dart';
import 'dart:async';
import 'fruit.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp(products: fetchFruit()));
class MyApp extends StatelessWidget {
final Future<List<Fruit>> products;
MyApp({this.products});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyHomePage(products: products),
);
}
}
class MyHomePage extends StatelessWidget {
final Future<List<Fruit>> products;
MyHomePage({this.products});
Future<void> _refreshProducts(BuildContext context) async {
return fetchFruit();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Rest API Demo"),
backgroundColor: Colors.cyan,
centerTitle: true,
),
body: Center(
child: RefreshIndicator(
onRefresh: () => _refreshProducts(context),
child: FutureBuilder<List<Fruit>>(
future: products,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return FruitItem(item: snapshot.data[index]);
},
)
: Center(child: CircularProgressIndicator());
},
),
),
));
}
}
Future fetchFruit() async {
final response = await http.get('url');
if (response.statusCode == 200) {
return decodeFruit(response.body);
} else {
throw Exception('Unable to fetch data from the REST API');
}
}
List<Fruit> decodeFruit(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Fruit>((json) => Fruit.fromMap(json)).toList();
}
Thanks for reading this article ❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
If we got something wrong? Let me know in the comments. we would love to improve.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.
We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.