1

I'm having screen with 3 tabs. All has different views. When user come to the screen, I've to hit the API and update the views for all 3 tabs. I'm not able to update view inside tabs. Not able to update the states of different tabs after getting API response.

Error

Error-> NoSuchMethodError: The method 'updateInfo' was called on null.
I/flutter ( 7515): Receiver: null
I/flutter ( 7515): Tried calling: updateInfo(Instance of 'OwnerInfo')

View of Screen is like:

enter image description here

DetailItem

class DetailItem extends StatefulWidget {
  PropertyItem _propertyObj;
  OwnerInfo _ownerInfo;
  Review _reviewInfo;

  @override
  _DetailItemState createState() => _DetailItemState();
}

class _DetailItemState extends State<DetailItem> with TickerProviderStateMixin {
  ScrollController _scrollController = new ScrollController();
  double _appBarHeight = 0.0;
  TabController _tabController;

  final GlobalKey<AddressViewTabState> key =
      new GlobalKey<AddressViewTabState>();

  //Tabs used in Detail Screen
  DetailViewTab _detailViewTab;
  AddressViewTab _addressViewTab;
  ReviewTab _reviewTab;

  @override
  void initState() {
    _tabController = TabController(length: 3, vsync: this, initialIndex: 0); // initialize tab controller
    //Initialize Tabs
    _detailViewTab = DetailViewTab(widget._propertyObj);
    _addressViewTab = AddressViewTab(key: key, propertyDetailModel: widget._ownerInfo);
    _reviewTab = ReviewTab(widget._propertyObj);

    _hitDetailAPI(); //init state Hit API
    super.initState();
  }

  //Detail API
  void _hitDetailAPI() async {
    Future<PropertyDetailModel> obj = APIHandler()
        .getPropertyDetail(widget._propertyObj.getRoomId.toString());
    obj.then((response) {
      if (!mounted) {
        return;
      }
      //update data in set state
      setState(() {
        if (response != null && response.getPropertyItem != null) {
          widget._propertyObj = response.getPropertyItem; // update data to property object the 1st tab(Detail)
          widget._ownerInfo = response.getOwnerInfo; // update data to owner info object the second tab (Address)
          key.currentState.updateInfo(widget._ownerInfo); // Tried to update the address tab view by calling through key current state.
        }
      });
    }).catchError((error) {
      print("Error-> " + error.toString());
    });
  }

AddressViewTab

class AddressViewTab extends StatefulWidget {
  OwnerInfo ownerInfo = OwnerInfo();
  AddressViewTab({ Key key , @required this.ownerInfo}) : super(key: key);

  @override
  AddressViewTabState createState() => AddressViewTabState();

}

class AddressViewTabState extends State<AddressViewTab>{

  updateInfo(OwnerInfo ownerInfo){
    print("Update method called");
    if (!mounted) {
      return;
    }
    setState(() {
      widget.ownerInfo=ownerInfo; // update state 
    });
  }

  @override
  Widget build(BuildContext context) {
      return Container(
          alignment: Alignment.center,
          child: ListView(
            children: <Widget>[
              getOwnerInfoCard(widget.ownerInfo),
            ],
          ),
        );
  }

}

Any help would be appreciated. Thanks in advance.

Anuj Sharma
  • 4,294
  • 2
  • 37
  • 53
  • check this answer may be helpful in resolving your problem https://stackoverflow.com/questions/52124380/trigger-firstpages-setstate-method-after-popping-second-page/52124773#52124773 – Sher Ali Sep 07 '18 at 10:37
  • This ans might be helpful - https://stackoverflow.com/a/51468131/5407008 – Tushar Pol Sep 07 '18 at 11:11
  • Thanks but I just got the answer after posting my question over here. I used ValueNotifier class from dart. When I get the response I just update the value in that notifier and in initState just pass the value from ValueNotifier to local object. It worked – Anuj Sharma Sep 07 '18 at 11:12
  • 1
    What you are doing is definitely not recommended. You have to lift up your state to the next common ancestor – boformer Sep 07 '18 at 16:59
  • I agree with @boformer. You have to lift your state one level up and all the tabs will get data from there. – Dinesh Balasubramanian Sep 07 '18 at 18:24

3 Answers3

0

You could use the flutter implementation of Redux for things like this https://pub.dartlang.org/packages/flutter_redux for this.

In short, this can make 'any' widget update itself when some data changes.

Marijn
  • 800
  • 7
  • 14
0

I already answered this question here https://stackoverflow.com/a/63832366/13439617

You can use callbacks to do this job

Muhammad Tameem Rafay
  • 3,602
  • 2
  • 21
  • 32
0

From pushing stateFul widget:

GestureDetector(
            onTap: () async {
             dynamic result = await Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) => CreateUser(
                    usersObj: usersObj,
                  )));
             if (result != null) {
               setState(() {
                 usersObj = result;
               });
             }
            },

From pop stateFul widget:

    Navigator.pop(context,usersObj);
Anil Kumar
  • 1,830
  • 15
  • 24