Значение не обновляется, несмотря на то, что потребитель вызывается после notifyListeners с использованием пакета поставщика

#flutter #flutter-provider

#flutter #flutter-provider

Вопрос:

Я с нетерпением жду возможности передать объект и динамическое значение с моей страницы 1 на мою страницу 2. Я решил использовать пакет поставщика и установил свою страницу 1 в качестве notificationProvider. (Я мог бы создать независимый класс с объектом, который я хочу использовать, но я не хотел добавлять ко многим потребителям на странице 1, где в основном используется мой объект).

Проблема, с которой я сталкиваюсь, заключается в том, что динамическое значение lastWords не обновляется на странице 2, несмотря notifyListeners на то, что и Consumer вызывается, когда переменная изменяет значение на странице 1.

Любой совет, что может быть не так в моем коде?

 void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => _MainPgState(),
      child: 
        MaterialApp(
        title: 'Routes',
        initialRoute: '/',
        routes: {
          '/': (context) => MainPg(),
          '/speech': (context) => SpeechCapturePg(),
        },   
  )));
}

class MainPg extends StatefulWidget  {
  @override
  _MainPgState createState() => _MainPgState();
}

// >>>>> PAGE 1 >>>>>
class _MainPgState extends State<MainPg> with ChangeNotifier {
  var lastError = "";   // dynamic variable to be passed to page2
  var lastStatus = "";
  bool _available = false;
  stt.SpeechToText speech = stt.SpeechToText();

  void errorListener(SpeechRecognitionError error) {
    setState(() {
      lastError = "${error.errorMsg} - ${error.permanent}";
      // >>>> Here, costumer is notified that lastError has changed.      
      notifyListeners(); });
      speech.stop();
    });
  }

  Future<void> initSpeechState() async {
    bool available = await speech.initialize(
      onError: errorListener);
    setState(() {
      _available = available;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (!_available) {
      initSpeechState();
    } 
    return Scaffold(
      appBar: AppBar(
        title: Text("--"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Started:$_available',
                style: TextStyle(
                  color: _available ? Colors.green : Colors.black,
                  fontSize: 15,
                )),
            Align(
              child: Stack(
                  alignment: AlignmentDirectional.bottomCenter,
                  children: <Widget>[
                    SizedBox(
                      width: 110.0,
                      height: 110.0,
                      child: Visibility(
                        visible: !speech.isListening,
                        child: FloatingActionButton(
                          onPressed: () {
                            if (_available) {
                              // >>> Here called page2
                              Navigator.pushNamed(
                                context,
                                '/speech',
                              );
                            } else {
                              initSpeechState();
                            }},
                      ))]),
            )]), 
      ),);}
}

///>>>>>  PAGE 2
class SpeechCapturePg extends StatefulWidget {
  @override
  _SpeechCapturePgState createState() => _SpeechCapturePgState();
}

class _SpeechCapturePgState extends State<SpeechCapturePg> {

  @override
  void initState() {
    super.initState();
    startListening(context);
  }

  @override
  dispose() {
    super.dispose();
  }

  void startListening(BuildContext context) {  
    // >>> Here the speech object is used in page 2 and is working well
    context.read<_MainPgState>().speech.listen( 
      cancelOnError: true,
    );
  }
  
  @override
  Widget build(BuildContext context) {
     return Scaffold(
        backgroundColor: Colors.redAccent,     
        body: Center( 
              // >>>> Here, lastError not returning the expected value
              Consumer<_MainPgState>(
              builder: (context, object, child) => Text(
                'Error:${object.lastError}',
                    style: TextStyle(
                    color: Colors.black,
                    fontSize: 15,
                  ))
              ),    
        )
      );
  }
}
 

Комментарии:

1. Вы неправильно используете провайдера. Я рекомендую вам изучить управление состоянием в Flutter ( flutter.dev/ docs/ development/data-and-backend/state-mgmt / intro ) и получить более глубокое представление о пакете поставщика для правильной реализации.

2. @Lee3 можете ли вы привести хотя бы одну часть моего кода, не соответствующую документации? Моя реализация Provider это почти то же самое в примере счетчика на flutter.dev.

3. Почти уверен, что документы не предлагают смешивать ChangeNotifier State один Widget из них и использовать его для обновления другого Widget своим собственным State . Вам нужно создать новый класс , который будет служить моделью , содержащей информацию , которой будут делиться оба Widgets .