0

I was trying to get the list page refreshed if a method was run on another page. I do pass the context using the push navigation.

I tried to follow these 3 answers Answer 1 Answer 2 and Answer 3 and I am not able to manage the states here.

This is the first list page which needs to be refreshed. It calls a class

class _PageLocalState extends State<PageLocal> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Expanded(
            child: SafeArea(
                child: ListView.builder(
              scrollDirection: Axis.vertical,
              shrinkWrap: true,
              itemCount: widget.allLocal.length,
              //padding: const EdgeInsets.only(top: 10.0),
              itemBuilder: (context, index) {
                return LocalCard(widget.allLocal[index]);
              },
            )),
          )
        ],
      ),
    );
  }
}

The next class:

class LocalCardState extends State<LocalCard> {
  FavData localdet;

  LocalCardState(this.localdet);

  ListTile makeListTile() => ListTile(
        contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
        title: Text(
          localdet.name,
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
        subtitle: Text(localdet.loc),
        trailing: Icon(Icons.keyboard_arrow_right, size: 30.0),
        onTap: () => navigateToDetail(localdet),
      );

  Widget get localCard {
    return new Card(
        elevation: 4.0,
        margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
        child: Container(
          child: makeListTile(),
        ));
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: localCard,
    );
  }

  navigateToDetail(FavData localdet) {
    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => FavouriteDetailPage(
                  mndet: localdet,
                )));
    setState(() {});
  }
}

Now this is routing to the final detail page:

class _FavouriteDetailPageState extends State<FavouriteDetailPage> {
  bool isFav = false;
  FavData mndet;
  _FavouriteDetailPageState(this.mndet);

  // reference to our single class that manages the database
  final dbHelper = DatabaseHelper.instance;

  @override
  Widget build(BuildContext context) {
    Widget heading = new Container(...);

    Widget middleSection = new Expanded(...);

    Widget bottomBanner = new Container(...);

    Widget body = new Column(...);

    final makeBottom = Container(
      height: 55.0,
      child: BottomAppBar(
        color: Color.fromRGBO(36, 36, 36, 1.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            new FavIconWidget(mndet),
          ],
        ),
      ),
    );

    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text('The Details'),
        backgroundColor: Color.fromRGBO(36, 36, 36, 1.0),
      ),
      body: Container(
        child: Card(
          elevation: 5.0,
          shape: RoundedRectangleBorder(
            side: BorderSide(color: Colors.white70, width: 1),
            borderRadius: BorderRadius.circular(10),
          ),
          margin: EdgeInsets.all(20.0),
          child: Padding(
            padding: new EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
            child: body,
          ),
        ),
      ),
      bottomNavigationBar: makeBottom,
    );
  }

  void share(BuildContext context, FavData mndet) {
    final RenderBox box = context.findRenderObject();
    final String shareText = "${mndet.name} - ${mndet.desc}";
    Share.share(shareText,
        subject: mndet.loc,
        sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
  }
}

class FavIconWidget extends StatefulWidget {
  final FavData mnforIcon;
  FavIconWidget(this.mnforIcon);
  @override
  _FavIconWidgetState createState() => _FavIconWidgetState();
}

class _FavIconWidgetState extends State<FavIconWidget> {
  final dbHelper = DatabaseHelper.instance;

  Future<bool> get isFav async {
    final rowsPresent = await dbHelper.queryForFav(widget.mnforIcon.id);
    if (rowsPresent > 0) {
      print('Card Loaded - Its Favourite already');
      return false;
    } else {
      print('Card Loaded - It is not favourite yet');
      return true;
    }
  }

  void _insert() async {...}

  void _delete() async {...}

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<bool>(
        future: isFav,
        initialData:
            false, // you can define an initial value while the db returns the real value
        builder: (context, snapshot) {
          if (snapshot.hasError)
            return const Icon(Icons.error,
                color: Colors.red); //just in case the db return an error
          if (snapshot.hasData)
            return IconButton(
                icon: snapshot.data
                    ? const Icon(Icons.favorite_border, color: Colors.white)
                    : Icon(Icons.favorite, color: Colors.red),
                onPressed: () => setState(() {
                      if (!snapshot.data) {
                        print('Its favourite so deleting it.');
                        _delete();
                      } else {
                        print('Wasnt fav in the first place so inserting.');
                        _insert();
                      }
                    }));

          return CircularProgressIndicator(); //if there is no initial value and the future is not yet complete
        });
  }
}

I am sure this is just some silly coding I have done but just not able to find out. Where. I tried adding Navigator.pop(context); in different sections of the detail page and it fails.

Currently, I have to navigate back to the Favourites list page and then HomePage and then back to Favourites ListPage to refresh the list.

Vivian Lobo
  • 583
  • 10
  • 29
  • I don't fully understand your problem and not sure if the following will work but can you try the following. when creating LocalCard along with widget.allLocal[index] can you also pass setState and save it in the stateful widget as a stateSetter. And then in navigateToDetail add an await before the Navigator.push and then after that call the statesetter you saved previously. – Pratheesh Russell Jun 06 '20 at 17:30
  • Thanks will try it and keep you posted. The issue is basically, I get some data from a local DB and then use it as a List builder. From the Details Card page, a user can favourite that card. If it is, then it will go to a separate Favourites list. The list here does not refresh when the user unchecks favourites button from the details card. Hope that made a little sense. – Vivian Lobo Jun 06 '20 at 17:34
  • so do you want the function that populates all the data inside widget.allLocal to be run again when you return from the detail page? – Pratheesh Russell Jun 06 '20 at 18:10
  • Yes, that is right, but only when a condition is met. – Vivian Lobo Jun 06 '20 at 21:54
  • I am not entirely sure this will work so can you try this out and let me know. when creating LocalCard along with widget.allLocal[index] can you pass an instance of the class as this, ie "return LocalCard(widget.allLocal[index], this);" and save it in the stateful widget as a variable ie "var mainpage = ...". And then in navigateToDetail add an await before the Navigator.push and then after that call the update function ie like " mainpage.FunctionThatUpdates()". – Pratheesh Russell Jun 07 '20 at 04:16
  • Sorry, this did not work. – Vivian Lobo Jun 08 '20 at 15:47

1 Answers1

1

try this.. Anywhere you are using Navigator.pop or Navigator.push .. Instead of this use this:

      Navigator.pushReplacement(context,
        MaterialPageRoute(builder: (BuildContext context) => Password())
       );

        //instead of Password use the name of the page(the second page you want to go to)
Jesus Loves You
  • 261
  • 5
  • 17