Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android's onStart equivalent

I am building an app which has local database and I keep some infos about movies in that database. There is a screen called "Favorites" where I get the movies from local database and put them in a listview: Favorites Screen

And if I click any movie from that list, I will be directed to a new Screen where I can see movie details. In this screen, there is a button which removes the movie from local database.

Now my problem starts here: After I remove any movie from database and go back to "Favorites" Screen, I still see that movie in ListView. But I have already removed that movie from database. If I was doin this on Android platform, I would override onStart method and make a query to database, then update the listview. But in Flutter as long as I know, there is no method as onStart. So, what should I do?

class FavoritesScreen extends StatefulWidget {
  @override
  _FavoritesScreenState createState() => _FavoritesScreenState();
}

class _FavoritesScreenState extends State<FavoritesScreen> {
  var favoriteMovieDatabase = FavoriteMovieDatabase();
  List<MovieOverview> movieOverviewList = List<MovieOverview>();

  @override
  void initState() {
    super.initState();
    favoriteMovieDatabase
        .getAllFavoriteMovies()
        .then((List<MovieOverview> list) {
      setState(() {
        movieOverviewList = list;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Favorites")),
        body: MovieOverviewListView(movieOverviewList, "FAVORITE")
    );
  }
}



EDIT:

I have tried to use WidgetsBindingObserver but it did not help.

    @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    if(state == AppLifecycleState.resumed){
      favoriteMovieDatabase
          .getAllFavoriteMovies()
          .then((List<MovieOverview> list) {
        setState(() {
          movieOverviewList = list;
        });
      });
    }
  }

It did not even call this method.

like image 970
Ege Avatar asked Aug 17 '18 08:08

Ege


2 Answers

As a simple solution, you can await the result of a navigator push:

goToDetailPage(BuildContext context) async {

  await Navigator.of(context).pushNamed('movieDetail');

  // this is reached when the route is popped
  reloadData();
}

To make the code even more efficient, you can return a result from your detail route that signifies if the movie was deleted:

Navigator.pop(context, 'MOVIE_DELETED');

and

goToDetailPage(BuildContext context) async {
  final result = await Navigator.of(context).pushNamed<String>('movieDetail');

  if(result == 'MOVIE_DELETED') {
    reloadData();
  }    
}

In the long run, when there are more ways to change the database content (think of a semitransparent dialog where the movie list is still visible in background, or live updates), it would be better to move to some kind of reactive architecture similar to Room on Android.

like image 70
boformer Avatar answered Nov 10 '22 03:11

boformer


Assuming your problem happens when you use Navigator to push a new route, then you can use RouteAware mixin combined with RouteObserver and then overrides didPopNext method.

didPopNext is called whenever a route becomes visible again.

final RouteObserver<PageRoute> routeObserver = new RouteObserver<PageRoute>();
void main() {
  runApp(new MaterialApp(
    home: new Container(),
    navigatorObservers: [routeObserver],
  ));
}

class RouteAwareWidget extends StatefulWidget {
  State<RouteAwareWidget> createState() => new RouteAwareWidgetState();
}

// Implement RouteAware in a widget's state and subscribe it to the RouteObserver.
class RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context));
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  void didPopNext() {
    // TODO: query DB again
  }

  @override
  Widget build(BuildContext context) => new Container();
}
like image 5
Rémi Rousselet Avatar answered Nov 10 '22 02:11

Rémi Rousselet