Множественное хранилище Flutter Mobx не обновляет значение в наблюдателе

#flutter #mobx #provider #observers

#flutter #mobx #поставщик #наблюдатели

Вопрос:

Я использую Mobx в своем приложении flutter. У меня есть несколько хранилищ. Когда я пытаюсь обновить какое-либо значение в хранилище, оно обновляется, но не отражается на пользовательском интерфейсе.

main.dart

 void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider<LocationStore>(create: (_) => LocationStore()),
        Provider<UserStore>(create: (_) => UserStore()),
        Provider<RideStore>(create: (_) => RideStore()),
      ],
      child: MaterialApp(
        title: 'FLutter APp',
        theme: myTheme(),
        debugShowCheckedModeBanner: false,
//        home: HomePage(
//          title: 'Live Location'
//        ),
        initialRoute:  WelcomeScreen.id,
        routes: {
          HomePage.id: (context) => HomePage(title: 'Home',),
          ProfileScreen.id: (context) => ProfileScreen(),
          WelcomeScreen.id: (context) => WelcomeScreen(),
          RegistrationScreen.id: (context) => RegistrationScreen(),
          LoginScreen.id: (context) => LoginScreen(),
          FeedScreen.id: (context) => FeedScreen(),
          RecordTrackScreen.id: (context) => RecordTrackScreen(),
          SaveActivityScreen.id: (context) => SaveActivityScreen(),
          UserProfileScreen.id: (context) => UserProfileScreen(),
          RideDetailsScreen.id: (context) => RideDetailsScreen(),
          StatsScreen.id: (context) => StatsScreen(),
          FindInviteScreen.id: (context) => FindInviteScreen(),
          CommentsScreen.id: (context) => CommentsScreen(),
        },
      ),
    );
  }
}
  

экран

 @override
  Widget build(BuildContext context) {
    final store = Provider.of<LocationStore>(context);
    final rideStore = Provider.of<RideStore>(context);
    final userStore = Provider.of<UserStore>(context);


    return Scaffold(
      appBar: AppBar(
        title: Text('Record'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.info_outline),
            onPressed: () {},
          )
        ],
      ),
      body: Observer(
        builder: (_) => SingleChildScrollView(
          child: Center(
              child: Column(
                children: <Widget>[
                  // Text('isPermitted - ${isPermitted}'),
                  Container(
                    child: isPermitted != null amp;amp; isPermitted ? WeatherMainWidget() : Text(''),
                    height: (MediaQuery.of(context).size.height - 50.0) * 0.4,
                  ),
                  Container(
                    height: (MediaQuery.of(context).size.height - 50.0) * 0.45,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: <Widget>[
                        // Text('rideStore.getIsStarted - ${rideStore.getIsStarted} - $_isRunning'),
                        // if (rideStore.isStarted)
                        Divider(
                          indent: 10.0,
                          endIndent: 10.0,
                          thickness: 1.0,
                          color: color8,
                        ),
                        Observer(
                            builder: (_) => Row(
                            children: [
                              Text('${rideStore.getSport.name}'),
                              Expanded(
                                flex: 1,
                                child: CustomIconButton(
                                    iconData: rideStore.getSport.icon,
                                    iconColor: Theme.of(context).primaryColor,
                                    bgColor: Colors.transparent,
                                    onPress: () {
                                      SportBottomSheet(context, rideStore);
                                    },
                                  ),
                              ),
                            ],
                          ),
                        ),
                        Container(
                          child: Visibility(
                            child: RecordTrackScreen(),
                            visible: rideStore.isStarted,
                          ),
                        ),
                        if (!rideStore.isStarted)
                        Container(
                          width: 70.0,
                          height: 70.0,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.all(Radius.circular(50.0),),
                            color: Theme.of(context).primaryColor,
                          ),
                          child: Visibility(
                            visible: !rideStore.isStarted,
                            child: CustomIconButton(
                              iconData: Icons.play_arrow,
                              iconColor: Colors.white,
                              iconSize: 35.0,
                              onPress: () {
                                print('dsdsadsadsad');
                                startTrip(store, rideStore, userStore);
                              },
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  // ListenLocationWidget()
                ],
              ),
          ),
        ),
      ),
    );
  }


  Widget SportBottomSheet(BuildContext context, RideStore rideStore) {
    showModalBottomSheet(context: context, builder: (BuildContext bc) {
      return Container(
        color: Colors.white,
        child: ListView.builder(itemCount: 2, itemBuilder: (ctx, index) {
          final sport = rideStore.sports[index];
          return GestureDetector(
            child: ListTile(
              leading: Icon(sport.icon, size: 30.0, color: Colors.black,),
              title: Text(sport.name, style: TextStyle(
                fontSize: 20.0,
                color: Colors.black
              ),),
              onTap: () {
                print('SportBottomSheet $sport');
                rideStore.selectedSport = new Sport(
                    sport.icon,
                    sport.name
                );
                rideStore.recentSport = rideStore.recentSport;
                Navigator.pop(context);
                print('sport ${rideStore.getSport.name}');
              },
            ),
          );
        }),
      );
    });
  }
  

хранилище ride

 class Sport{
  final IconData icon;
  final String name;

  Sport(this.icon, this.name);
}

  List<Sport> sports = [
    new Sport(Icons.directions_walk_outlined, 'Walk'),
    new Sport(Icons.motorcycle, 'Ride'),
  ];

  @observable
  Sport recentSport;

  @observable
  Sport selectedSport;

  @computed
  Sport get getSport {
    if (selectedSport != null)
      return selectedSport;
    if (recentSport != null)
      return recentSport;

    return sports[0];
  }
  

Когда я проверяю значение getSport в методе onTap, оно показывает выбранное значение, но оно не обновляется в пользовательском интерфейсе.

Спасибо

Ответ №1:

Попробуйте изменить @computed на @action

 @action
Sport get getSport {
 if (selectedSport != null)
   return selectedSport;
 if (recentSport != null)
   return recentSport;

return sports[0];
  

}

или, может быть, использовать ObservableList или ObservableFuture

Ответ №2:

Используйте ObservableList следующим образом

 @observable
ObservableList<Sport> sports =[Sport(Icons.directions_walk_outlined, 'Walk'), new Sport(Icons.motorcycle, 'Ride'),];