Flutter - Implementing Pull to Refresh - GeeksforGeeks

01 Jun, 2021
The pull-to-refresh or (swipe-to-refresh) feature enables a user to pull down to fetch more data. The pull-to-refresh feature can be seen in many modern apps. The pull-to-refresh feature can be implemented in those components that are scrollable.
In this article, we are going to implement this feature in Flutter. If you are not familiar with flutter please visit flutter.dev before diving into this article. Flutter is all about widgets everything in flutter is nothing but widgets. Flutter also provides a widget to implement this feature as well as i.e RefreshIndicator.
RefreshIndicator: When the child’s Scrollable descendant overscrolls, an animated circular progress indicator is faded into view. When the scroll ends, if the indicator has been dragged far enough for it to become completely opaque, the onRefresh callback is called. The callback is expected to update the scrollable’s contents and then complete the Future it returns. The refresh indicator disappears after the callback’s Future has completed.
To create a flutter application open terminal/ command and run the below command:
flutter create app_name
// app_name should be the name of your app

Example:
flutter create demo_app
After running this command you should have a folder with the specified app_name. Navigate into that folder and open lib/main.dart file.
Note: In order to implement pull-to-refresh feature we are not going to use any other dependencies.
To create a RefreshIndicator use the below syntax:
RefreshIndicator(
  child: ...
  onRefresh: ...
)

These are required fields.
child: Should be a scrollable widget
onRefresh: A function that should return a future. 
       Future is a type in dart.
We are going to implement this step by step.
Step 1: As discussed above for RefreshIndicator to work we are going to need a scrollable component. So for that, we are going to use ListView. In this step, we are going to define some demo data for our app.
Dart
// Local State to display items in listviewList<String> _demoData; // This method will run once widget is loaded// i.e when widget is mounting@overridevoid initState() {  // initializing state / demo data  _demoData = [    "Flutter",    "React Native",    "Cordova/ PhoneGap",    "Native Script"  ];  super.initState();}
Step 2: We are going to create our ListView with ListItem and AlwaysScrollingPhysics.
Dart
... some code ListView.builder(  itemBuilder: (ctx, idx) {    // List Item    return Card(      child: ListTile(        title: Text(_demoData[idx]),      ),    );  },   // Length of the list  itemCount: _demoData.length,   // To make listView scrollable  // even if there is only a single item.  physics: const AlwaysScrollableScrollPhysics(),)   ... some code
Step 3: Finally wrapping ListView into RefreshIndicator to use pull-to-refresh feature.
Dart
... some code RefreshIndicator(  child: ListView.builder(    itemBuilder: (ctx, idx) {      // List Item      return Card(        child: ListTile(          title: Text(_demoData[idx]),        ),      );    },     // Length of the list    itemCount: _demoData.length,     // To make listView scrollable    // even if there is only a single item.    physics: const AlwaysScrollableScrollPhysics(),  ),  // Function that will be called when  // user pulls the ListView downward  onRefresh: () {    return Future.delayed(      Duration(seconds: 1),      () {        /// adding elements in list after [1 seconds] delay        /// to mimic network call        ///        /// Remember: setState is necessary so that        /// build method will run again otherwise        /// list will not show all elements        setState(() {          _demoData.addAll(["Ionic", "Xamarin"]);        });                 // showing snackbar        _scaffoldKey.currentState.showSnackBar(          SnackBar(            content: const Text('Page Refreshed'),          ),        );      },    );  },)   ... some code
Complete Source Code:
Dart
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'GeeksforGeeks',       // to hide debug banner      debugShowCheckedModeBanner: false,      theme: ThemeData(        primarySwatch: Colors.green,      ),      home: HomePage(),    );  }} /// [StatefulWidget] so that we can change/// internal state to show proper working/// of [PULL TO REFRESH] featureclass HomePage extends StatefulWidget {  @override  _HomePageState createState() => _HomePageState();} class _HomePageState extends State<HomePage> {  // ScaffoldKey object. This is required  // to show snackbar  // This is optional. This is not required always  GlobalKey<ScaffoldState> _scaffoldKey;   // Local State to display items in listview  List<String> _demoData;   // This method will run once widget is loaded  // i.e when widget is mounting  @override  void initState() {    // initializing states    _demoData = [      "Flutter",      "React Native",      "Cordova/ PhoneGap",      "Native Script"    ];    _scaffoldKey = GlobalKey();    super.initState();  }   // This method will run when widget is unmounting  @override  void dispose() {    // disposing states    _scaffoldKey?.currentState?.dispose();    super.dispose();  }   @override  Widget build(BuildContext context) {    return SafeArea(      child: Scaffold(        key: _scaffoldKey,        appBar: AppBar(          title: const Text('GeeksforGeeks'),        ),        // Widget to show RefreshIndicator        body: RefreshIndicator(          child: ListView.builder(            itemBuilder: (ctx, idx) {              // List Item              return Card(                child: ListTile(                  title: Text(_demoData[idx]),                ),              );            },             // Length of the list            itemCount: _demoData.length,             // To make listView scrollable            // even if there is only a single item.            physics: const AlwaysScrollableScrollPhysics(),          ),          // Function that will be called when          // user pulls the ListView downward          onRefresh: () {            return Future.delayed(              Duration(seconds: 1),              () {                /// adding elements in list after [1 seconds] delay                /// to mimic network call                ///                /// Remember: [setState] is necessary so that                /// build method will run again otherwise                /// list will not show all elements                setState(() {                  _demoData.addAll(["Ionic", "Xamarin"]);                });                 // showing snackbar                _scaffoldKey.currentState.showSnackBar(                  SnackBar(                    content: const Text('Page Refreshed'),                  ),                );              },            );          },        ),      ),    );  }}
Note: In some cases, you will notice that the refresh indicator is not showing.
      To make it visible all the time please use physics: In Flutter all the scrollable
      widgets have physics properties.
The below will enable scrolling even if there are only a few elements in the list.
ListView(
  physics: const AlwaysScrollableScrollPhysics(),
  ...
)
Output:
surinderdawra388
android
Flutter
Picked
Technical Scripter 2020
Dart
Flutter
Technical Scripter
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Flutter - Custom Bottom Navigation Bar
ListView Class in Flutter
Android Studio Setup for Flutter Development
Flutter - Flexible Widget
Flutter - Stack Widget
Flutter - Custom Bottom Navigation Bar
Flutter Tutorial
Flutter - Flexible Widget
Flutter - Stack Widget
Flutter - BorderRadius Widget