Stream builder not loading desired data at the first loading of the screen, then working as it should after changing tabs : Flutter

1,675

Solution 1

Okay, so after a lot of debugging, I figured what was the reason for not getting the desired contents in the body at the loading of the first tab, but in all the subsequent ones.

The only other noteworthy thing can be, that the reference made includes the name of the tab that is currently selected. However, since the tab shows appropriately, and all the other tabs work too, I am sure that, that is not something creating the issue.

What I was doing is, the reference call depended on the value in the presently selected tab i.e. for different tabs, different data would be pulled and displayed.

 @override
   void initState() {
   super.initState();    
  tabController = TabController(length: subCategoryList.length, vsync: this, initialIndex: 0);
  tabController.addListener(_setActiveTabIndex);
}

void _setActiveTabIndex() {
  activeTabIndex = tabController.index;
  setState(() {
    currentTab = subCategoryList[activeTabIndex].toString(); 
  });
}

Now, I was initializing the tabController in the initState() and using a listener to know which tab was currently active. On printing these values, I learnt that on the first load of the screen, the 'activeTabIndex' as well as 'currentTab' return null values. This was the case, when either loading the second screen for the first time, or coming back into the first screen and selecting another option to come again into this screen.

As a result, it returned the desired values in the contents, whenever a different tab was selected, apart from the first one.

To solve this problem, I set the default value of currentTab to always load the contents based on the first tab that would show on the loading of the page. This, I did by adding a line in the initState() as:

  @override
   void initState() {
   super.initState(); 

  currentTab = subCategoryList[0].toString();
  tabController = TabController(length: subCategoryList.length, vsync: this, initialIndex: 0);
  tabController.addListener(_setActiveTabIndex);
 }

And now, whenever the page gets loaded, I get the desired contents in the body, as the values have already been initialized by the time the widget to display the contents gets built.

Solution 2

Have you tried flipping your StreamBuilder on its head i know it seams like it might not matter but I've seen it make a difference let me know if this helped.

StreamBuilder(

  stream: Firestore.instance
          . //Required Reference//     
          .snapshots(),

  builder: (BuildContext context, AsyncSnapshot <QuerySnapshot>snapshot) {


    if (snapshot.hasData){
      if(snapshot.data.documents.length > 0){
 var someData = snapshot.data.documents;
    List<dynamic> someDocs = someData;

         RequiredList1 = [];
      ..... More such statements ..........
      RequiredList11 = [];

      for(int i =0; i < someDocs.length; i++){

        RequiredList1.add(someData[i]['field1']);
        ....... More such calls ................
        RequiredList11.add(someData[i]['field11']);            

      } 

      }else{
           return WidgetToShowContents
      }


    }else{
      CircularProgressIndicator();
    }


  }
     );
Share:
1,675
Chirag Rajgariah
Author by

Chirag Rajgariah

Updated on December 19, 2022

Comments

  • Chirag Rajgariah
    Chirag Rajgariah over 1 year

    I am using a Stream builder to populate the contents of the body of different tabs on a screen using Flutter. The stream builder fetches data from Firebase and passes these values in different lists, which are used in a listView builder to display the contents.

    The tabs on the screen are supposed to change, based on the selection on the previous screen. This part works well. However,

    Problem 1:

    On the initial loading of the screen, the contents from all the tabs show under the tab that is initially selected. Only when I swipe right once, i.e. go to some other tab, I get the desired contents on the screen, meaning the respective contents under the respective tabs.

    Problem 2:

    If I go back from this screen onto the previous screen and make a different selection, again ... On the first tab that opens up on this screen, I get the contents from the previous tab that was loaded before hitting the back button. Only when a different tab is selected, I get the desired output.

    This signifies that the code written works, but only under certain conditions. The tabs load exactly as expected, even on the first attempt, only the contents under the tab are an issue ... that too, only on the first screen of loading. This clearly signifies that there is something wrong with the stream builder, but I can't seem to figure out what, exactly.

    The layout of my code using stream builder is:

     body : StreamBuilder(
      
      stream: Firestore.instance
              . //Required Reference//     
              .snapshots(),
      
      builder: (BuildContext context, AsyncSnapshot <QuerySnapshot>snapshot) {
        
        var someData = snapshot.data.documents;
        List<dynamic> someDocs = someData;
    
        if (snapshot.hasData == null){
          return CircularProgressIndicator(),}
    
    
        else if (snapshot.data.documents.length > 0){ 
    
          RequiredList1 = [];
          ..... More such statements ..........
          RequiredList11 = [];
    
          for(int i =0; i < someDocs.length; i++){
      
            RequiredList1.add(someData[i]['field1']);
            ....... More such calls ................
            RequiredList11.add(someData[i][field11']);            
    
          } 
           return WidgetToShowContents
          
           }
          }
         );
    

    The only other noteworthy thing can be, that the reference made includes the name of the tab that is currently selected. However, since the tab shows appropriately, and all the other tabs work too, I am sure that, that is not something creating the issue.

    I have thought of using the dispose method to get rid of the stream builder to counter Problem 2, but I have no idea how to implement that with a stream builder, nor am I sure if that is gonna work.

  • Chirag Rajgariah
    Chirag Rajgariah about 4 years
    Doing this doesn't change anything, unfortunately. It might help in some other things, I think. Do you have any other ideas I could use to get rid of this issue? Thanks! :)