В приведенном ниже примере, поскольку MyStatefulWidget
имеет состояние, не имеет значения, вызывается ли setState
на _MyAppState
, потому что оно не будет перерисовано.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
int value = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('App Example')),
body: Row(children:[
MyStatefulWidget(title: value.toString()),
RaisedButton(
textColor: Colors.white,
color: Colors.blue,
onPressed: (){setState(() { value+=1; });},
child: new Text("Add"),
)
]),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key, this.title}):super(key: key);
final String title;
@override
State<StatefulWidget> createState() {
return _MyStatefulWidgetState();
}
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String title;
@override
void initState() {
super.initState();
if (widget.title!=null) {
title = widget.title;
} else {
title = "";
}
}
int value = 0;
@override
Widget build(BuildContext context) {
return Text(title);
}
}
Если бы я использовал StatelessWidget
, он был бы перерисован, но это всего лишь пример, бывают случаи, когда мне нужно перерисовать StatefulWidget
, когда вызывается setState
.
Одним из вариантов было бы дать ему имя и построить его из setState, но мне нужно, чтобы он рисовался в том месте, где он рисуется прямо сейчас.
Дартпад: https://dartpad.dev/968be8755d5deab1ca5c8c84a993eafc
отредактируйте вопрос, чтобы было очень ясно о результате и о том, что было испробовано до сих пор
Вы можете напрямую использовать widget.title в текстовом виджете для обновления счетчика на экране. Пожалуйста, смотрите код ниже:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
void changeVal(int val) {
setState(() {
value = val;
});
}
int value = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('App Example')),
body: Row(children: [
MyStatefulWidget(
title: value.toString(),
groupValue: value % 10,
chnageVal: changeVal),
RaisedButton(
textColor: Colors.white,
color: Colors.blue,
onPressed: () {
setState(() {
value += 1;
});
},
child: const Text("Add"),
)
]),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key key, this.title, this.groupValue, this.chnageVal})
: super(key: key);
final String title;
final int groupValue;
final Function(int) chnageVal;
@override
State<StatefulWidget> createState() {
return _MyStatefulWidgetState();
}
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
//String title;
// @override
// void initState() {
// super.initState();
// if (widget.title!=null) {
// title = widget.title;
// } else {
// title = "";
// }
// }
//int value = 0;
List<int> numbers = List.generate(10, (index) => index);
@override
Widget build(BuildContext context) {
return Container(
width: 120,
child: Column(children: [
Text(widget.title),
...numbers
.map((number) => RadioListTile<int>(
title: Text('$number'),
value: number,
groupValue: widget.groupValue,
onChanged: (val) {
widget.chnageVal(val);
},
))
.toList()
]),
);
}
}
Это был просто пример. Предположим, что вместо текста MyStatefulWidget
была радиогруппой. Сам MyStatefulWidget
может изменить состояние радиогруппы, но я также хочу иметь возможность установить радиогруппу из родительского
Я обновил код. Я добавил группу Radio из 10 RadioListTile со значением от 0 до 9. Теперь каждый раз, когда вы нажимаете кнопку Add
, виджет Text
будет обновляться на value
, как и раньше. Однако в зависимости от последней цифры value
группа радио также будет обновлена.
Основная проблема в том, что вы все еще читаете widget.groupValue
, я не могу этого сделать, потому что виджет радио (MyStatefulWidget
в вашем случае) должен иметь возможность изменять выбранный переключатель при нажатии на него. Поэтому мы не можем использовать константу widget.groupVale
.
Я открыл награду, пожалуйста, посмотрите
Обновлен код, теперь вы можете щелкнуть радиокнопку, и значение радиокнопки станет значением текста. Таким образом, значение передается обратно.
Просто предоставьте уникальный ключ при вызове MyStatefulWidget
, как MyStatefulWidget(key: UniqueKey(), title: value.toString()),
.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
int value = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('App Example')),
body: Row(children: [
MyStatefulWidget(key: UniqueKey(), title: value.toString()),
RaisedButton(
textColor: Colors.white,
color: Colors.blue,
onPressed: () {
setState(() {
value += 1;
});
},
child: new Text("Add"),
)
]),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key, this.title}) : super(key: key);
final String title;
@override
State<StatefulWidget> createState() {
return _MyStatefulWidgetState();
}
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String title;
@override
void initState() {
super.initState();
if (widget.title != null) {
title = widget.title;
} else {
title = "";
}
}
int value = 0;
@override
Widget build(BuildContext context) {
return Text(title);
}
}
Чтобы узнать больше о ключе, ознакомьтесь с этой статьей.
Я рекомендую использовать Stream, лучшую производительность и не так сложно использовать для частичного обновления пользовательского интерфейса.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
StreamController<int> _streamController = StreamController();
int value = 0;
@override
void dispose() {
_streamController.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home:
StreamBuilder<int>(
stream: _streamController.stream,
initialData: value,
builder:
(BuildContext context, AsyncSnapshot<int> snapshot) {
return Scaffold(
appBar: AppBar(title: Text('App Example')),
body: Row(children:[
MyStatefulWidget(title: value.toString()),
RaisedButton(
textColor: Colors.white,
color: Colors.blue,
onPressed: (){_streamController.sink.add(value++);},
child: new Text("Add"),
)
]),
);},),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key, this.title}):super(key: key);
final String title;
@override
State<StatefulWidget> createState() {
return _MyStatefulWidgetState();
}
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String title;
@override
void initState() {
super.initState();
if (widget.title!=null) {
title = widget.title;
} else {
title = "";
}
}
int value = 0;
@override
Widget build(BuildContext context) {
return Text(title);
}
}
Вопрос не ясен. Ответ @bluenile правильный, но похоже, что вы хотите добиться чего-то другого, чем то, о чем вы просите.