#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
.