无法将变量的更新状态从屏幕/页 1 动态传递到屏幕/页 2



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

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

到目前为止我尝试过的:

  1. 通过GlobalKey传递lastError,但它只在构建屏幕2的小部件时传递状态,而不是像在屏幕1中那样普通地传递状态
  2. 在屏幕2中添加errorHandling方法,但对象总是在屏幕1中调用errorHandling方式
  3. 正在为密钥.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),                  
])));
}
}

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

相关内容

  • 没有找到相关文章

最新更新