Flutter - Stateful Widget не сохраняет состояние счетчика при переключении вкладок
Я учусь трепетать, я работаю с tabBars, и у меня возникла проблема с сохранением состояния. Ниже приведен небольшой рабочий пример моей проблемы. В основном, есть кнопка и счетчик состояния. Когда я нажимаю кнопку, я вижу правильное обновление текстового поля. Но когда я переключаюсь на другую вкладку и возвращаюсь, текстовое поле возвращается к нулю.
Я обнаружил, что если переместить следующую строку за пределы _CounterState, чтобы она была определена на верхнем уровне файла, то она работает правильно. Когда я переключаю вкладки, счетчик остается на правильное количество, когда я переключаю обратно
int _counter = 0;
Я не чувствую, что это подходящий способ сделать это, и все примеры, которые я видел, имеют переменную внутри класса. Кто-нибудь может дать мне какие-либо идеи? Зачем его сбрасывать, если он внутри класса? Я должен держать это вне класса? Ниже приведен упрощенный полный пример.
import 'package:flutter/material.dart';
void main() {
runApp(new TabBarDemo());
}
class TabBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
tabs: [
new Tab(icon: new Icon(Icons.directions_car)),
new Tab(icon: new Icon(Icons.directions_transit)),
new Tab(icon: new Icon(Icons.directions_bike)),
],
),
title: new Text('Tabs Demo'),
),
body: new TabBarView(
children: [
new Counter(),
new Icon(Icons.directions_transit),
new Icon(Icons.directions_bike),
],
),
),
),
);
}
}
class Counter extends StatefulWidget {
@override
_CounterState createState() => new _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return new Row(
children: <Widget>[
new RaisedButton(
onPressed: _increment,
child: new Text('Increment'),
),
new Text('Count: $_counter'),
],
);
}
}
Ниже приведен пример со счетчиком, перемещенным за пределы класса.
import 'package:flutter/material.dart';
void main() {
runApp(new TabBarDemo());
}
class TabBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
tabs: [
new Tab(icon: new Icon(Icons.directions_car)),
new Tab(icon: new Icon(Icons.directions_transit)),
new Tab(icon: new Icon(Icons.directions_bike)),
],
),
title: new Text('Tabs Demo'),
),
body: new TabBarView(
children: [
new Counter(),
new Icon(Icons.directions_transit),
new Icon(Icons.directions_bike),
],
),
),
),
);
}
}
class Counter extends StatefulWidget {
@override
_CounterState createState() => new _CounterState();
}
int _counter = 0; //<-- MOVED OUTSIDE THE _CounterState CLASS
class _CounterState extends State<Counter> {
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return new Row(
children: <Widget>[
new RaisedButton(
onPressed: _increment,
child: new Text('Increment'),
),
new Text('Count: $_counter'),
],
);
}
}
1 ответ
Как _CounterState
виджет строится каждый раз, когда вы идете в данный TabView вам нужно поставить _counter
переменная в классе конфигурации состояния (Counter
).
class Counter extends StatefulWidget {
int _counter = 0;
@override
_CounterState createState() => new _CounterState();
}
class _CounterState extends State<Counter> {
void _increment() {
setState(() {
widget._counter++;
});
}
@override
Widget build(BuildContext context) {
return new Row(
children: <Widget>[
new RaisedButton(
onPressed: _increment,
child: new Text('Increment'),
),
new Text('Count: ${widget._counter}'),
],
);
}
}
Как я использовал одно решение
AutomaticKeepAliveClientMixin
Вам нужно использовать этот миксин с вашим классом состояния StateFullWidget.
вам нужно передать истинный к wantKeepAlive метод получения.
class SampleWidget extends StatefulWidget {
@override
_SampleWidgetState createState() => _SampleWidgetState();
}
class _SampleWidgetState extends State<SampleWidget> with AutomaticKeepAliveClientMixin{
@override
Widget build(BuildContext context) {
return Container();
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
Это сохранит ваше состояние и остановит воссоздание вашего виджета. Я использовал его с Tabbar и PageView, и он работает нормально.
Поместите переменную в этот statefulwidget и затем каждый раз вызывайте ее как "widget.variable_name"