如何使用键强制重绘有状态小部件?
How to force stateful widget redraw using keys?
我正在制作一个从 API 中提取数据并将其显示在视图(MVC 样式)中的应用程序。
我需要弄清楚如何强制我的视图小部件重绘自身。现在我尝试使用 ValueKeys 和 ObjectKeys 但无济于事。
有很多很多代码,所以我将尽可能使用片段来保持清晰。 (如果您需要查看更多代码,请随时询问)
这是我的视图小部件:
class view extends StatefulWidget{
view({
Key key,
this.count = 0,
}) : super(key: key);
int count;
String _action='';
var _actionParams='';
var _data;
Function(String) callback;
void setAction(String newAction){
_action = newAction;
}
void setActionParams(String params){
_actionParams = jsonDecode(params);
}
void setData(String data){
_data = jsonDecode(data);
}
void incrementCounter(){
count++;
}
@override
_viewState createState() => _viewState();
}
class _viewState extends State<view>{
Object redrawObject = Object();
@override
Widget build(BuildContext context) {
/*
switch(widget._action){
case '':
break;
default:
return null;
}
*/
return Text("Counter: "+widget.count.toString());
}
@override
void initState(){
this.redrawObject = widget.key;
super.initState();
}
}
您可以在注释代码中看到我计划更改视图根据传递给它的数据构建自身的方式。
到目前为止我尝试的是在构造函数中将 ValueKey/ObjectKey 传递给 main.dart 的视图,然后在运行时更改对象。不幸的是,这没有用。
在我的 main.dart(可从 main 中的任何地方访问)的顶部,我有这个:
Object redraw = Object();
final dataView = new view(key: ObjectKey(redraw));
然后在主页正文中我有视图和一个浮动按钮。
如果我按下按钮,它应该增加视图内的计数器并强制它重绘。这是我到目前为止尝试过的代码:
body: Center(
child: dataView
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.badge),
onPressed: (){
dataView.incrementCounter();
redraw = new Object();
},
),
据我了解,如果用作键的对象发生更改,则 flutter 应该重建小部件的状态。所以我将我的对象设置为一个新对象,但它不起作用。
我也试过这样的:
onPressed: (){
setState((){
dataView.incrementCounter();
redraw = new Object();
});
},
最终我想将导航器与我的视图小部件结合使用(以便我们有一个后退按钮),但我不知道这是否可行。
感觉有点和框架斗智斗勇了。我应该使用不同的范例吗(比如页面?)或者我可以这样做吗?
如何强制重新绘制视图小部件?
你可以check flutter_phoenix重绘效果的逻辑。我认为它非常有用,或者您可以直接使用包本身。基本上它会完成您想要实现的目标。
它在状态中创建一个唯一的键。
Key _key = UniqueKey();
将其注入容器。
@override
Widget build(BuildContext context) {
return Container(
key: _key,
child: widget.child,
);
}
当你调用 rebirth 时,它只是刷新键,这会导致视图重建。
void restartApp() {
setState(() {
_key = UniqueKey();
});
}
使用 Göktuğ Vatandaş 的答案和 GlobalKeys 我能够弄明白。
我在状态中创建了一个 reDraw() 函数,然后我使用 GlobalKey 从我的 main 调用它。
注意:不需要包装在容器中并使用容器的密钥。调用 setState() 足以强制重绘。
这是新的视图小部件:
import 'dart:convert';
import 'package:flutter/cupertino.dart';
GlobalKey<_viewState> viewKey = GlobalKey();
class view extends StatefulWidget{
view({
Key key,
this.count = 0,
}) : super(key: key);
int count;
String _action='';
var _actionParams='';
var _data;
Function(String) callback;
void setAction(String newAction){
_action = newAction;
}
void setActionParams(String params){
_actionParams = jsonDecode(params);
}
void setData(String data){
_data = jsonDecode(data);
}
void incrementCounter(){
count++;
}
@override
_viewState createState() => _viewState();
}
class _viewState extends State<view>{
@override
Widget build(BuildContext context) {
/*
switch(widget._action){
case '':
break;
default:
return null;
}
*/
return Text("Counter: "+widget.count.toString());
}
@override
void initState(){
super.initState();
}
void reDraw(){
setState((){});
}
}
这是我在 main 中声明视图小部件的位置:
final dataView = new view(key: viewKey);
这里是我调用 reDraw() 函数的地方:
floatingActionButton: FloatingActionButton(
child: Icon(Icons.badge),
onPressed: (){
dataView.incrementCounter();
viewKey.currentState.reDraw();
},
),
谢谢 Göktuğ Vatandaş!
我正在制作一个从 API 中提取数据并将其显示在视图(MVC 样式)中的应用程序。
我需要弄清楚如何强制我的视图小部件重绘自身。现在我尝试使用 ValueKeys 和 ObjectKeys 但无济于事。
有很多很多代码,所以我将尽可能使用片段来保持清晰。 (如果您需要查看更多代码,请随时询问)
这是我的视图小部件:
class view extends StatefulWidget{
view({
Key key,
this.count = 0,
}) : super(key: key);
int count;
String _action='';
var _actionParams='';
var _data;
Function(String) callback;
void setAction(String newAction){
_action = newAction;
}
void setActionParams(String params){
_actionParams = jsonDecode(params);
}
void setData(String data){
_data = jsonDecode(data);
}
void incrementCounter(){
count++;
}
@override
_viewState createState() => _viewState();
}
class _viewState extends State<view>{
Object redrawObject = Object();
@override
Widget build(BuildContext context) {
/*
switch(widget._action){
case '':
break;
default:
return null;
}
*/
return Text("Counter: "+widget.count.toString());
}
@override
void initState(){
this.redrawObject = widget.key;
super.initState();
}
}
您可以在注释代码中看到我计划更改视图根据传递给它的数据构建自身的方式。
到目前为止我尝试的是在构造函数中将 ValueKey/ObjectKey 传递给 main.dart 的视图,然后在运行时更改对象。不幸的是,这没有用。
在我的 main.dart(可从 main 中的任何地方访问)的顶部,我有这个:
Object redraw = Object();
final dataView = new view(key: ObjectKey(redraw));
然后在主页正文中我有视图和一个浮动按钮。 如果我按下按钮,它应该增加视图内的计数器并强制它重绘。这是我到目前为止尝试过的代码:
body: Center(
child: dataView
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.badge),
onPressed: (){
dataView.incrementCounter();
redraw = new Object();
},
),
据我了解,如果用作键的对象发生更改,则 flutter 应该重建小部件的状态。所以我将我的对象设置为一个新对象,但它不起作用。
我也试过这样的:
onPressed: (){
setState((){
dataView.incrementCounter();
redraw = new Object();
});
},
最终我想将导航器与我的视图小部件结合使用(以便我们有一个后退按钮),但我不知道这是否可行。
感觉有点和框架斗智斗勇了。我应该使用不同的范例吗(比如页面?)或者我可以这样做吗?
如何强制重新绘制视图小部件?
你可以check flutter_phoenix重绘效果的逻辑。我认为它非常有用,或者您可以直接使用包本身。基本上它会完成您想要实现的目标。
它在状态中创建一个唯一的键。
Key _key = UniqueKey();
将其注入容器。
@override
Widget build(BuildContext context) {
return Container(
key: _key,
child: widget.child,
);
}
当你调用 rebirth 时,它只是刷新键,这会导致视图重建。
void restartApp() {
setState(() {
_key = UniqueKey();
});
}
使用 Göktuğ Vatandaş 的答案和 GlobalKeys 我能够弄明白。
我在状态中创建了一个 reDraw() 函数,然后我使用 GlobalKey 从我的 main 调用它。
注意:不需要包装在容器中并使用容器的密钥。调用 setState() 足以强制重绘。
这是新的视图小部件:
import 'dart:convert';
import 'package:flutter/cupertino.dart';
GlobalKey<_viewState> viewKey = GlobalKey();
class view extends StatefulWidget{
view({
Key key,
this.count = 0,
}) : super(key: key);
int count;
String _action='';
var _actionParams='';
var _data;
Function(String) callback;
void setAction(String newAction){
_action = newAction;
}
void setActionParams(String params){
_actionParams = jsonDecode(params);
}
void setData(String data){
_data = jsonDecode(data);
}
void incrementCounter(){
count++;
}
@override
_viewState createState() => _viewState();
}
class _viewState extends State<view>{
@override
Widget build(BuildContext context) {
/*
switch(widget._action){
case '':
break;
default:
return null;
}
*/
return Text("Counter: "+widget.count.toString());
}
@override
void initState(){
super.initState();
}
void reDraw(){
setState((){});
}
}
这是我在 main 中声明视图小部件的位置:
final dataView = new view(key: viewKey);
这里是我调用 reDraw() 函数的地方:
floatingActionButton: FloatingActionButton(
child: Icon(Icons.badge),
onPressed: (){
dataView.incrementCounter();
viewKey.currentState.reDraw();
},
),
谢谢 Göktuğ Vatandaş!