Search code examples
flutterflutter-layout

Flutter - How to refresh some Page from PageView with a button?


I have a Stateful class, and the return of build is a PageView, and each one of pages have a Scafold and a body.

What I need is, my first page have in Scafold a action Button, to refresh the entire page (or rebuild my entire class, if I can).

I try create a setState in onTap from button, and create a StreamController, but, none of them resolve my problem.

import 'package:flutter/material.dart';
import 'package:plataforma_base/animations/loader.dart';
import 'package:plataforma_base/pages/home_body.dart';
import '../constantes/constantes.dart';
import 'dart:async';


class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final _pageController = PageController(
    initialPage: 0,
  );

  final StreamController _stream = StreamController.broadcast();


  @override
  void dispose() {
    _stream.close();
    super.dispose();
  }

  void _refreshPage(){
    _stream.sink.add(null);
  }

  @override
  Widget build(BuildContext context) {
    return
      PageView(
        controller: _pageController,
        scrollDirection: Axis.vertical,
        physics: NeverScrollableScrollPhysics(),
        children: <Widget>[
          Scaffold(
              appBar: new AppBar(
                title: new Text(
                  "HOME",
                ),
                backgroundColor: Color(Cores.corPrincipal),
                centerTitle: true,
                actions: <Widget>[
                  IconButton(
                      icon: Icon(Icons.refresh,color: Colors.white,),
                      onPressed: (){
                        _refreshPage();
                      }
                  ),
                ],
              ),
              drawer: CustomDrawer(_pageController),
            body: StreamBuilder(
                initialData: HomeBody(),
                stream: _stream.stream,
                builder: (context, snapshot){
                  Dialog(
                    child: Loader(),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(20),
                    ),
                    insetAnimationCurve: Cubic(2, 5, 10, 3),
                    insetAnimationDuration: Duration(seconds: 30),
                  );
                  return HomeBody();
                },
            ),
          ),
        ],
      );
  }
}

If i miss some important information, please tell my to paste here.


Solution

  • This seems to be an interesting use case. The sample code you've provided is incomplete and I'm unable to run it locally. However, I did try a similar setup in this sample app. If a Stateful widget is used as a page in a PageView, calling it's setState() should refresh the individual pages.

    Here's a sample that you can check. The FloatingActionButton triggering the refresh action is in the Home page, while the refresh() function it invokes is in Page 1.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      var page1 = Page1();
    
      @override
      Widget build(BuildContext context) {
        debugPrint('HomePage build');
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: PageView(
              children: [
                page1,
                _page2(),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.refresh),
            backgroundColor: Colors.blueAccent,
            onPressed: () {
              debugPrint('Refresh Page 1');
              page1.getState().refresh();
            },
          ),
        );
      }
    
      _page2() {
        return Container(
          color: Colors.greenAccent,
        );
      }
    }
    
    class Page1 extends StatefulWidget {
      Page1State page1State;
    
      @override
      Page1State createState() {
        page1State = Page1State();
        return page1State;
      }
    
      getState() => page1State;
    }
    
    class Page1State extends State<Page1> {
      var refreshCount = 0;
    
      refresh() {
        debugPrint('Page 1 refresh');
        setState(() {
          refreshCount++;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        debugPrint('Page 1 build');
        return Container(
          color: Colors.lightBlueAccent,
          child: Center(
            child: Text('Refresh clicked $refreshCount times'),
          ),
        );
      }
    }
    

    Demo

    demo