Adding Swipe To Refresh to Flutter app

Dhiraj Sharma
Published in
3 min readAug 16, 2018


In Android app you can implement swipe to refresh by wrapping your ListView(or GridView) inside SwipeRefreshLayout, while in iOS UIRefreshControl is used for same.

For Flutter there is RefreshIndicator

A widget that supports the Material “swipe to refresh” idiom.

When child of RefreshIndicator is over scrolled , an animated circular progress indicator is displayed & onRefresh callback is called. Callback returns a future, after complete of which UI is updated & refresh indicator disappears.

In this example we will load random user profile using free API RandomUser, which provides random user on each refresh.

First things first , lets create a StatefulWidget & State for that widget.

class SwipeToRefreshExample extends StatefulWidget {
State<StatefulWidget> createState() {
return _SwipeToRefreshState();
class _SwipeToRefreshState extends State<SwipeToRefreshExample{
Widget build(BuildContext context) {
// Implementation later

Now lets create User model & network call to fetch user

class User {
final String name, image;

User(, this.image);

factory User.fromJson(Map<String, dynamic> json) {
json = json['results'][0];
String name = json['name']['first'] + " " + json['name']['last'];
String image = json['picture']['large'];
return User(name, image);
Future<User> getUser() async {
final response = await http.get("");
final responseJson = json.decode(response.body);
return User.fromJson(responseJson);

More on network call on flutter

Now lets create default user data & implement build method(of State).

//Inside _SwipeToRefreshState
User user = User("Default User",
//Inside build of _SwipeToRefreshStatereturn Scaffold(
appBar: AppBar(
title: Text("Refresh Indicator"),
body: Padding(
padding: const EdgeInsets.only(top: 24.0),
child: Center(
child: Column(
children: <Widget>[, height: 128.0, width: 128.0),
SizedBox(height: 24.0),

At this moment if we start SwipeToRefreshExample widget output will be default user with placeholder image.

Things to remember while implementing RefreshIndicator is

  • RefreshIndicator requires key to implement state.
  • onRefresh(RefreshCallback) method required completable future.
  • child is typically ListView or CustomScrollView.

Add RefreshIndicatorState inside our state class

final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();

Update body of build inside state : Wrap code we wrote above inside build to ListView & then RefreshIndicator.

body: RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: _refresh,
child: ListView(children: [
// body of above

_refresh() method : this method call getUser() which returns User on future. When user is returned by getUser(), our user(of state) is updated & setState is called for rebuild.

Future<Null> _refresh() {
return getUser().then((_user) {
setState(() => user = _user);

Done our SwipeToRefresh is ready.

One thing missing here is user needs to swipe to see data at start, we can make data load automatically at start by updating indicator state inside initState once widget is build.

void initState() {
.addPostFrameCallback((_) =>;

Now if you want to add a refresh button on toolbar which acts same as swipe. Update AppBar, add actions as

actions: <Widget>[
new IconButton(
icon: const Icon(Icons.refresh),
tooltip: 'Refresh',
onPressed: () {;

Full code for this example is available here

Thanks ! Question & Feedback Welcome !!

The Flutter Pub is a medium publication to bring you the latest and amazing resources such as articles, videos, codes, podcasts etc. about this great technology to teach you how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium or learn more about us here. We’d love to connect! And if you are a writer interested in writing for us, then you can do so through these guidelines.