Carrein
Carrein

Reputation: 3371

Refresh a listview outside of a widget in Flutter?

I have a Flutter application which comprises of a scaffold with a slider and a tabview.

The tabview comprises of a List which is show on each tab as seen in the picture below.

  List<Widget> widgetList = <Widget>[
    Post(),
    Feed(),
    Location(),
    HomePage(),
    Feed(),
  ];

Now I would like to refresh the current tab on screen when the slider is moved. However, since the classes are private i.e. _HomePageState, I do not know how to access the refreshList() method as shown in the snippet below.

homepage.dart:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {
  var list;
  var random;

  var refreshKey = GlobalKey<RefreshIndicatorState>();

  @override
  void initState() {
    super.initState();
    random = Random();
    refreshList();
  }

  Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await Future.delayed(Duration(seconds: 2));

    setState(() {
      list = List.generate(random.nextInt(10), (i) => "Item $i");
    });

    return null;
  }
}

The slider is not baked into each listview Widget i.e. homepage.dart as the slider values is applicable to each individual tab. How can I refresh the inner listview widget when the outer widget with the slider is moved?

enter image description here

Upvotes: 8

Views: 11036

Answers (1)

boformer
boformer

Reputation: 30123

There are different ways to deal with this:

  1. You could pass down the PageController and the page index to your page widgets. In your page widgets can then listen to the changes (pageController.addListener(...)) and compare the currently centered page with their page index.

  2. Create one ChangeNotifier for every page that you want to refresh:

    final postRefresh = ChangeNotifier();
    final feedRefresh = ChangeNotifier();
    ...
    
    // build method of parent:
    List<Widget> widgetList = <Widget>[
      Post(refresh: postRefresh),
      Feed(refresh: feedRefresh),
      ...
    ];
    
    // initState method of parent:
    pageController.addListener(() {
      final roundedPage = pageController.page.round();
      if(roundedPage == 0) {
        postRefresh.notifyListeners();
      }
      else if(roundedPage == 1) {
        feedRefresh.notifyListeners();
      }
      // ...
    })
    
  3. You could also give your page widgets a global key (for that, their State classes must be public):

    // class body of parent:
    final postPageKey = GlobalKey<PostPageState>();
    final feedPageKey = GlobalKey<FeedPageState>();
    
    // build method of parent:
    List<Widget> widgetList = <Widget>[
      Post(key: postPageKey),
      Feed(key: feedPageKey),
      ...
    ];
    
    // initState method of parent:
    pageController.addListener(() {
      final roundedPage = pageController.page.round();
      if(roundedPage == 0) {
        postPageKey.currentState?.refresh();
      }
      else if(roundedPage == 1) {
       feedPageKey.currentState?.refresh();
      }
      // ...
    })
    

Upvotes: 7

Related Questions