无法将变量的更新状​​态动态地从 screen/page 1 传递到 screen/page 2

Can't pass updated state of variable dynamically from screen/page 1 to screen/page 2

我在屏幕 1 中创建了一个实例化的对象(语音),然后调用该对象的初始化方法,我在其中设置错误处理(var lastError 获取错误输出)。然后我使用 Navigator.pushNamed 将对象作为参数传递给屏幕 2,我在其中调用了一些其他语音方法。

我面临的问题是,当在屏幕 2 中出现错误时,我无法获得错误输出,因为初始化和错误捕获是在屏幕 1 中定义的。

到目前为止我尝试过的:

  1. 通过 GlobalKey 传递 lastError,但它仅传递屏幕 2 的小部件构建时的状态,但不像屏幕 1 中那样动态地传递。
  2. 在屏幕 2 中添加 errorHandling 方法,但对象始终在屏幕 1 中调用 errorHandling 方法。
  3. 为 key.currentState.lastError 添加 setState,但无论如何它都不是动态更新的。

我无法将初始化调用传递到页面 2,因为在传递到屏幕 2 以录制语音之前,我需要确认对象在屏幕 1 中工作。

关于如何在屏幕 2 中动态更新错误的任何建议?

class PassedSpeechComponent {
  stt.SpeechToText speech;
  String lastError;
  PassedSpeechComponent(this.speech, this.lastError, this.lastStatus);
}

final key = new GlobalKey<_MainPgState>();

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

class MainPg extends StatefulWidget {
  MainPg({ Key key }) : super(key: key);
  @override
  _MainPgState createState() => _MainPgState();
}

// ***** SCREEN 1 ******
class _MainPgState extends State<MainPg> {
  var lastError = "";
  var lastStatus = "";
  bool _available = false;
  stt.SpeechToText speech = stt.SpeechToText();

  // speech error listener of 1st screen
  void errorListener(SpeechRecognitionError error) { 
     setState(() {
      lastError = "${error.errorMsg} - ${error.permanent}";
      print('@@@ Called error listener of 1st screen @@@');
    });
    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('Initializing:$_available',
                style: TextStyle(
                  color: _available ? Colors.green : Colors.black,
                  fontSize: 15,
                )),
            Text('isListening:${speech.isListening}',
                style: TextStyle(
                  color: speech.isListening ? Colors.green : Colors.black,
                  fontSize: 15,
                )),
                Text('Error:' + lastError, // LastError alert on first screen working as intended.
                    style: TextStyle(
                      color:
                        lastError != "" ? Colors.red : 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) {
                              Navigator.pushNamed(
                                context,
                                '/speech',
                                arguments: {speech, errorListener, statusListener},
                              );
                            } else {
                              initSpeechState();
                            }
                          },
                          tooltip: 'A single tap is enough',
                          child: Icon(Icons.mic),
                        ),
                      ),
                    ),
                  ]),
            ),
          ],
        ),
      ),
      );
  }
}

// ******** SECOND SCREEN ********
class SpeechCapturePg extends StatefulWidget {
  final String title;

const SpeechCapturePg({Key key, this.title}) : super(key: key);
  @override
  _SpeechCapturePgState createState() => _SpeechCapturePgState();
}

class _SpeechCapturePgState extends State<SpeechCapturePg>
    with TickerProviderStateMixin {
  String lastWords = "";
  String lastError = "";
  
  @override
  void initState() {
    super.initState();
   
    WidgetsBinding.instance.addPostFrameCallback((_) {
      startListening(ModalRoute.of(context).settings.arguments);
    });

      setState(()
      {
        // Here I try to update dinamically lastError anytime 
        // last error of first screen is updated, but is not working... =(
        lastError = key.currentState.lastError;
        print("Last Error" + key.currentState.lastError);
      });
  }

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

  // This method is never called in this screen/page, just the one created in screen 1 
  void errorListener(SpeechRecognitionError error) {
    setState(() {
      print('Called in 2nd screen:'$lastError);
    });
  }

  
  void startListening(speech) {
    lastWords = "";
    lastError = "";    
    // 
    speech.first.listen(
      onResult: resultListener,
      cancelOnError: true,
    );
  }

  void resultListener(SpeechRecognitionResult result) {
    setState(() {
      lastWords = "${result.recognizedWords}";
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.redAccent,
        body: Center(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                    flex: 30,
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child:
                        Text('$lastWords')
                  )),
                  //***** HERE I NEED TO SHOW THE ERROR REPORTED BY OBJECT *****/                        
                  Text('Error - $lastError'),
                  // **** 2ND TRY TO SHOW ERROR REPORTED IN FIRST SCREEN
                  Text('Error' + key.currentState.lastError),                  
            ])));
  }
}

您正在尝试在两个视图之间共享状态。为此,您需要一个状态管理解决方案。查看 Provider 包。这是Flutter团队推荐的方法。