如何在Flutter中使用Speech To Text Provider实现多组件复用及回调处理
用Provider封装Speech To Text实现多Widget复用
1. 添加依赖
首先在pubspec.yaml里引入所需依赖包:
dependencies: flutter: sdk: flutter speech_to_text: ^6.4.0 # 建议使用最新稳定版本 provider: ^6.0.5 # 建议使用最新稳定版本
2. 实现SpeechToText Provider类
新建speech_provider.dart文件,把语音识别的核心逻辑、状态管理和回调处理都封装在这里:
import 'package:flutter/material.dart'; import 'package:speech_to_text/speech_to_text.dart'; import 'package:speech_to_text/speech_recognition_result.dart'; import 'package:speech_to_text/speech_recognition_error.dart'; class SpeechProvider extends ChangeNotifier { final SpeechToText _speechToText = SpeechToText(); bool _isListening = false; String _lastWords = ''; String _lastError = ''; String _currentStatus = ''; // 对外暴露的状态变量 bool get isListening => _isListening; String get lastWords => _lastWords; String get lastError => _lastError; String get currentStatus => _currentStatus; // 初始化语音识别,检查权限 Future<void> initSpeech() async { final hasPermission = await _speechToText.initialize( onStatus: _onStatusChanged, onError: _onErrorOccurred, ); if (!hasPermission) { _lastError = '未获取语音识别权限'; notifyListeners(); } } // 开始语音识别 void startListening() async { if (!_speechToText.isAvailable) { await initSpeech(); } _isListening = true; _lastWords = ''; _lastError = ''; notifyListeners(); await _speechToText.listen( onResult: _onSpeechResult, listenMode: ListenMode.confirmation, cancelOnError: true, ); } // 停止语音识别 void stopListening() { _isListening = false; _speechToText.stop(); notifyListeners(); } // 识别结果回调处理 void _onSpeechResult(SpeechRecognitionResult result) { _lastWords = result.recognizedWords; notifyListeners(); } // 状态变化回调处理 void _onStatusChanged(String status) { _currentStatus = status; notifyListeners(); } // 错误回调处理 void _onErrorOccurred(SpeechRecognitionError error) { _lastError = '${error.errorMsg} - ${error.permanent ? "永久错误" : "临时错误"}'; _isListening = false; notifyListeners(); } }
3. 在应用根节点注入Provider
修改main.dart,用ChangeNotifierProvider包裹整个应用,让所有子Widget都能访问到这个Provider:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'speech_provider.dart'; import 'speech_demo_page.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => SpeechProvider(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '语音转文本演示', theme: ThemeData(primarySwatch: Colors.blue), home: const SpeechDemoPage(), ); } }
4. 多Widget中调用语音功能
新建speech_demo_page.dart,拆分不同功能的Widget,共享Provider中的状态:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'speech_provider.dart'; class SpeechDemoPage extends StatelessWidget { const SpeechDemoPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('语音转文本演示')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ const SpeechControlButton(), const SizedBox(height: 20), const SpeechResultCard(), const SizedBox(height: 20), const SpeechStatusPanel(), ], ), ), ); } } // 控制开始/停止的按钮Widget class SpeechControlButton extends StatelessWidget { const SpeechControlButton({super.key}); @override Widget build(BuildContext context) { final speechProvider = Provider.of<SpeechProvider>(context); return ElevatedButton( onPressed: speechProvider.isListening ? speechProvider.stopListening : speechProvider.startListening, child: Text(speechProvider.isListening ? '停止识别' : '开始说话'), ); } } // 显示识别结果的卡片Widget class SpeechResultCard extends StatelessWidget { const SpeechResultCard({super.key}); @override Widget build(BuildContext context) { final speechProvider = Provider.of<SpeechProvider>(context); return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Text( speechProvider.lastWords.isEmpty ? '等待语音输入...' : '识别内容:${speechProvider.lastWords}', style: const TextStyle(fontSize: 16), ), ), ); } } // 显示状态和错误信息的面板Widget class SpeechStatusPanel extends StatelessWidget { const SpeechStatusPanel({super.key}); @override Widget build(BuildContext context) { final speechProvider = Provider.of<SpeechProvider>(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('当前状态:${speechProvider.currentStatus}', style: const TextStyle(color: Colors.grey)), if (speechProvider.lastError.isNotEmpty) Text('错误提示:${speechProvider.lastError}', style: const TextStyle(color: Colors.red)), ], ); } }
核心说明
- 整个应用仅初始化一次
SpeechToText实例,放在Provider中统一管理,避免重复初始化导致的异常。 - 所有状态变更后调用
notifyListeners(),确保依赖状态的Widget自动刷新。 onStatus、onError等回调统一在Provider内部处理,不用在每个Widget中重复编写逻辑。- 多个Widget通过
Provider.of获取共享状态,实现跨Widget的语音功能复用。
内容的提问来源于stack exchange,提问作者teacherman_wsls
相关产品推荐
相关产品推荐

