'Flutter Pull To Refresh
I've implemented this code to show a list of json data from a web url. I've tried to implement a simple pull to refresh, but nothing works.
Flutter code is long, but it's pretty simple actually. It has main classes of flutter, and a future method to load json data from web.
I just want to implement a simple pull to refresh.
What am I missing here?
Why is it not working?
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:pull_to_refresh/pull_to_refresh.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'XXX',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'XXX'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  final RefreshController _refreshController = RefreshController();
  Future<List<User>> _getUsers() async {
    var data = await http.get("xxxxxxxxxxxxx");
    if (data.statusCode == 200) {
        print('Status Code 200: Ok!');
        var jsonData = json.decode(data.body);
        List<User> users = [];
        for (var k in jsonData.keys) {
          var u = jsonData[k];
          //print(u["pubdate"]);
          User user = User(u["id"], u["source"], u["desc"], u["link"], u["title"], u["img"], u["pubdate"]);
          users.add(user);
        }
        print(users.length);
        return users;
    } else {
      throw Exception('Failed to load json');
    }
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SmartRefresher(
        controller: _refreshController,
        enablePullDown: true,
        header: WaterDropHeader(),
        onRefresh: () async {
          await Future.delayed(Duration(seconds: 1));
          _refreshController.refreshCompleted();
        },
        child: FutureBuilder(
            future: _getUsers(),
            builder: (BuildContext context, AsyncSnapshot snapshot){
              if(snapshot.data == null){
                return Container(
                  child: Center(
                    child: Text("Loading..."),
                  ),
                );
              } else {
                return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int id){
                return ListTile(
                  leading: CircleAvatar(
                    backgroundImage: NetworkImage(
                        snapshot.data[id].img
                    ),
                  ),
                  title: Text(snapshot.data[id].title),
                  subtitle: Column(
                    children: <Widget>[
                      Row(
                          children: [
                          Text(
                            snapshot.data[id].source,
                            overflow: TextOverflow.fade,
                            maxLines: 1,
                            softWrap: false,
                          ),
                          Spacer(),
                          Text(snapshot.data[id].pubdate),
                          ],
                      ),
                    ],
                  )
                );
                },
                );
              }
            },
          ),
      ),
    );
  }
}
class User {
  final int id;
  final String source;
  final String desc;
  final String link;
  final String title;
  final String img;
  final String pubdate;
  User(this.id, this.source, this.desc, this.link, this.title, this.img, this.pubdate);
}
Solution 1:[1]
Solved!
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'XXXX',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'XXXXXX'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  //Funcao para buscar as noticias
  Future<List<User>> _getUsers() async {
    var data = await http.get("XXXXX");
    if (data.statusCode == 200) {
        print('Status Code 200: Ok!');
        var jsonData = json.decode(data.body);
        List<User> users = [];
        for (var k in jsonData.keys) {
          var u = jsonData[k];
          //print(u["pubdate"]);
          User user = User(u["id"], u["source"], u["desc"], u["link"], u["title"], u["img"], u["pubdate"]);
          users.add(user);
        }
        print(users.length);
        return users;
    } else {
      throw Exception('Failed to load json');
    }
  }
  var refreshKey = GlobalKey<RefreshIndicatorState>();
  @override
  void initState() {
    super.initState();
    refreshList();
  }
  Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      _getUsers();
    });
    return null;
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: RefreshIndicator(
        key: refreshKey,
        child: FutureBuilder(
            future: _getUsers(),
            builder: (BuildContext context, AsyncSnapshot snapshot){
              if(snapshot.data == null){
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else {
                return ListView.builder(
                itemCount: snapshot.data.length,
                itemBuilder: (BuildContext context, int id){
                return ListTile(
                  leading: CircleAvatar(
                    backgroundImage: NetworkImage(
                        snapshot.data[id].img
                    ),
                  ),
                  title: Text(snapshot.data[id].title),
                  subtitle: Column(
                    children: <Widget>[
                      Row(
                          children: [
                          Text(
                            snapshot.data[id].source,
                            overflow: TextOverflow.fade,
                            maxLines: 1,
                            softWrap: false,
                          ),
                          Spacer(),
                          Text(snapshot.data[id].pubdate),
                          ],
                      ),
                    ],
                  )
                );
                },
                );
              }
            },
        ),
        onRefresh: refreshList,
      ),
    );
  }
}
class User {
  final int id;
  final String source;
  final String desc;
  final String link;
  final String title;
  final String img;
  final String pubdate;
  User(this.id, this.source, this.desc, this.link, this.title, this.img, this.pubdate);
}
Solution 2:[2]
You have to get users on onLoading as shown below
@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Text(widget.title),
  ),
  body: SmartRefresher(
    ....
    onLoading: _getUsers,
    .....
  )
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | grc | 
| Solution 2 | 
