refresh the data from network using future builder on clicking the onpressed action from another dart class

I have a stateful widget class app_body.dart and which will fetch some data from the API and display using the future builder. below is the sample code from app_body.dart

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

import './my_app_bar.dart';

class AppBody extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _AppBodyState();
  }
}

class _AppBodyState extends State<AppBody> {

  Future _fetchLogData() async {
    final response = await http.get('api url');
    if (response.statusCode == 200) {
      return UserDetailHandler.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load post');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: MyAppBar(_fetchLogData),
      body: Center(
        child: FutureBuilder(
          future: _fetchLogData(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Container(
                  child: Column(children: <Widget>[
                    Text('Last Synced' + ' ' + snapshot.data.lastUpdatedAt)]));
            } else if (snapshot.hasError) {
              return Text("${snapshot.error}");
            }
            return CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}

// class which instantiate all the details from the API Part
class UserDetailHandler {
  final String lastUpdatedAt;

// constructor to intialise
  UserDetailHandler({this.lastUpdatedAt});

// assign values to the class object
  factory UserDetailHandler.fromJson(Map<String, dynamic> json) {
    return UserDetailHandler(lastUpdatedAt: json['updated_at']);
  }
}

Also upon clicking on the refresh icon on another stateless class called my_app_bar.dart which holds the AppBar and actions to be performed. My aim is to refresh the data displayed in the app_body.dart To do that, I just passed my API calling method to the stateless widget and call it on the onPressed action of the my_app_bar refresh button. The API is called, but the data is not refreshed.

Below is the sample code from my_app_bar.dart

import 'package:flutter/material.dart';

class MyAppBar extends StatelessWidget implements PreferredSizeWidget {

  final Function refreshLogData;
  MyAppBar(this.refreshLogData);

  @override
  Widget build(BuildContext context) {
    return AppBar(
        actions: <Widget>[
          IconButton(
            icon: new Icon(Icons.refresh),
            alignment: Alignment.topCenter,
            tooltip: 'refresh the Data',
            onPressed: () {
              print('log data');
              refreshLogData();
            },
          )
        ],
        title: Center(
            child: Text(
          'Random Data',
          textAlign: TextAlign.center,
        )));
  }

  @override
  Size get preferredSize => new Size.fromHeight(kToolbarHeight);
}

Am I missing something or do I need to do extra above said. I have found much articles to refresh the data when the button is present in the AppBody part. Here, My code has 2 files and the refresh icon is existed in another class of appBar.

Please advise, TIA.

1 answer

  • answered 2019-05-22 08:04 Sibin

    From the provided code change these lines

    ........
     IconButton(
                .....
                .....
                onPressed: refreshLogData,
              )
            ],
    
    .........
    

    then the refreshLogData method will work and after completion of Server call, you need to refresh the screen using setState.

    A better suggestion is instead of Future use StreamBuilder then it will work seamlessly.