我在Flutter中有一个Dropzone.autoDiscover = false;
$(document).ready(function(){
$("#mydropzone").dropzone({
init: function() {...}
);
});
按钮,使用StatefulWidget
将我导航到另一个StatefulWidget
。在第二个小部件上,我正在改变全局状态(一些用户首选项)。当我从第二个小部件返回到第一个小部件时,使用Navigator.push()
第一个小部件处于旧状态,但我想强制它重新加载。知道怎么做吗?我有一个想法,但它看起来很难看:
答案 0 :(得分:13)
简单技巧是使用 Navigator.pushReplacement 方法
第1页
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Page2(),
),
);
第2页
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Page1(),
),
);
答案 1 :(得分:11)
你可以在这里做几件事。 @ Mahi的回答虽然正确可能会更简洁,实际上使用push而不是showDialog,正如OP所询问的那样。这是一个使用Navigator.push
:
import 'package:flutter/material.dart';
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
color: Colors.green,
child: new Column(
children: <Widget>[
new RaisedButton(
onPressed: () => Navigator.pop(context),
child: new Text("back"),
),
],
),
);
}
}
class FirstPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new FirstPageState();
}
class FirstPageState extends State<FirstPage> {
Color color = Colors.white;
@override
Widget build(BuildContext context) {
return new Container(
color: color,
child: new Column(
children: <Widget>[
new RaisedButton(
child: new Text("next"),
onPressed: () {
Navigator
.push(
context,
new MaterialPageRoute(builder: (context) => new SecondPage()),
)
.then((value) {
setState(() {
color = color == Colors.white ? Colors.grey : Colors.white;
});
});
}),
],
),
);
}
}
void main() => runApp(
new MaterialApp(
builder: (context, child) => new SafeArea(child: child),
home: new FirstPage(),
),
);
但是,还有另一种方法可以很好地适应您的用例。如果您使用global
作为影响第一页构建的内容,则可以使用InheritedWidget来定义全局用户首选项,每次更改时,您的FirstPage都将重建。这甚至可以在无状态小部件中工作,如下所示(但也应该在有状态小部件中工作)。
flutter中的inheritedWidget的一个例子是应用程序的主题,虽然它们在一个小部件中定义它,而不是像我这里那样直接构建它。
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
color: Colors.green,
child: new Column(
children: <Widget>[
new RaisedButton(
onPressed: () {
ColorDefinition.of(context).toggleColor();
Navigator.pop(context);
},
child: new Text("back"),
),
],
),
);
}
}
class ColorDefinition extends InheritedWidget {
ColorDefinition({
Key key,
@required Widget child,
}): super(key: key, child: child);
Color color = Colors.white;
static ColorDefinition of(BuildContext context) {
return context.inheritFromWidgetOfExactType(ColorDefinition);
}
void toggleColor() {
color = color == Colors.white ? Colors.grey : Colors.white;
print("color set to $color");
}
@override
bool updateShouldNotify(ColorDefinition oldWidget) =>
color != oldWidget.color;
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var color = ColorDefinition.of(context).color;
return new Container(
color: color,
child: new Column(
children: <Widget>[
new RaisedButton(
child: new Text("next"),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new SecondPage()),
);
}),
],
),
);
}
}
void main() => runApp(
new MaterialApp(
builder: (context, child) => new SafeArea(
child: new ColorDefinition(child: child),
),
home: new FirstPage(),
),
);
如果您使用继承的窗口小部件,则不必担心会看到您推送的页面的弹出窗口,这将适用于基本用例,但最终可能会在更复杂的场景中出现问题。
答案 2 :(得分:9)
有两件事,从
传递数据在第一页中使用此
// sending "Foo" from 1st
Navigator.push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));
在第二页中使用它。
class Page2 extends StatelessWidget {
final String string;
Page2(this.string); // receiving "Foo" in 2nd
...
}
在第二页中使用此
// sending "Bar" from 2nd
Navigator.pop(context, "Bar");
在第1页中使用它,它与以前使用的相同,但几乎没有修改。
// receiving "Bar" in 1st
String received = await Navigator.push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));
答案 3 :(得分:8)
只需在 page1() 上的 Navigator.push 之后添加 .then((value) { setState(() {});
,如下所示:
Navigator.push(context,MaterialPageRoute(builder: (context) => Page2())).then((value) { setState(() {});
现在,当您从 page2 使用 Navigator.pop(context)
时,您的 page1 会自行重建
答案 4 :(得分:5)
这项工作真的很好,我是从以下文档中获得的:flutter doc
我定义了从首页控制导航的方法。
_navigateAndDisplaySelection(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddDirectionPage()),
);
//below you can get your result and update the view with setState
//changing the value if you want, i just wanted know if i have to
//update, and if is true, reload state
if (result) {
setState(() {});
}
}
因此,我在墨水池的action方法中调用它,但是也可以从按钮中调用它:
onTap: () {
_navigateAndDisplaySelection(context);
},
最后在第二页中,要返回一些内容(我返回了布尔值,您可以返回任意值):
onTap: () {
Navigator.pop(context, true);
}
答案 5 :(得分:5)
onTapFunction(BuildContext context) async {
final reLoadPage = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => IdDetailsScreen()),
);
if (reLoadPage) {
setState(() {});
}
}
现在在从第二页执行 Navigator.pop
返回第一页时只返回一些值,在我的情况下,如果 bool
输入
onTap: () {
Navigator.pop(context, true);
}
答案 6 :(得分:3)
我的解决方案是在SecondPage上添加一个函数参数,然后接收从FirstPage完成的重载函数,然后在Navigator.pop(context)行之前执行该函数。
第一页
refresh() {
setState(() {
//all the reload processes
});
}
然后继续推送到下一页...
Navigator.push(context, new MaterialPageRoute(builder: (context) => new SecondPage(refresh)),);
第二页
final Function refresh;
SecondPage(this.refresh); //constructor
然后在导航器弹出行之前
widget.refresh(); // just refresh() if its statelesswidget
Navigator.pop(context);
需要从上一页重新加载的所有内容都应在弹出窗口后进行更新。
答案 7 :(得分:3)
对我来说,这似乎可行:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
DRIVER_PATH = '/Users/jasonbeedle/Desktop/snaviescraper/chromedriver'
options = Options()
options.page_load_strategy = 'normal'
# Navigate to url
driver = webdriver.Chrome(options=options, executable_path=DRIVER_PATH)
driver.get("https://www.canalplus/programme-tv")
results = driver.find_elements_by_class(
'cardTitle')
print(results.text)
driver.quit
然后只需在孩子中调用Navigator.of(context).pushNamed("/myRoute").then((value) => setState(() {}));
。
答案 8 :(得分:2)
///将此位置推送到第二个屏幕(在异步功能中)
Function f;
f = await Navigator.pushNamed(context, 'Screenname');
f();
//将其放置在弹出的位置
Navigator.pop(context, () {
setState(() {});
});
///它的作用是在弹出后将setState函数作为参数传递给屏幕
答案 9 :(得分:1)
如果使用的是警报对话框,则可以使用在关闭对话框时完成的Future。将来完成后,您可以强制窗口小部件重新加载状态。
首页
onPressed: () async {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
....
);
}
);
setState(() {});
}
在警报对话框中
Navigator.of(context).pop();
答案 10 :(得分:1)
您可以在弹出上下文时传回dynamic result
,然后在值setState((){})
时调用true
,否则只需保持原状。
我已粘贴了一些代码段供您参考。
handleClear() async {
try {
var delete = await deleteLoanWarning(
context,
'Clear Notifications?',
'Are you sure you want to clear notifications. This action cannot be undone',
);
if (delete.toString() == 'true') {
//call setState here to rebuild your state.
}
} catch (error) {
print('error clearing notifications' + error.toString());
}
}
Future<bool> deleteLoanWarning(BuildContext context, String title, String msg) async {
return await showDialog<bool>(
context: context,
child: new AlertDialog(
title: new Text(
title,
style: new TextStyle(fontWeight: fontWeight, color: CustomColors.continueButton),
textAlign: TextAlign.center,
),
content: new Text(
msg,
textAlign: TextAlign.justify,
),
actions: <Widget>[
new Container(
decoration: boxDecoration(),
child: new MaterialButton(
child: new Text('NO',),
onPressed: () {
Navigator.of(context).pop(false);
},
),
),
new Container(
decoration: boxDecoration(),
child: new MaterialButton(
child: new Text('YES', ),
onPressed: () {
Navigator.of(context).pop(true);
},
),
),
],
),
) ??
false;
}
此致 鳅
答案 11 :(得分:1)
推送后只需使用“then”,当导航器弹出时,它将触发 setState 并且视图将刷新。
Navigator.push(blabla...).then((value) => setState(() {}))
答案 12 :(得分:0)
需要强制重建我的无状态小部件之一。不想使用有状态。想出了这个解决方案:
await Navigator.of(context).pushNamed(...);
ModalRoute.of(enclosingWidgetContext);
请注意,context和enclosingWidgetContext可以是相同或不同的上下文。例如,如果您从StreamBuilder内部推送,它们将有所不同。
我们在这里不使用ModalRoute做任何事情。单独订阅的行为足以强制重建。
答案 13 :(得分:0)
这个简单的代码对我有用,它可以进入根目录并重新加载状态:
...
onPressed: () {
Navigator.of(context).pushNamedAndRemoveUntil('/', ModalRoute.withName('/'));
},
...
答案 14 :(得分:0)
简而言之,您应该使小部件监视状态。为此,您需要状态管理。
我的方法基于Flutter Architecture Samples和Flutter Docs中说明的提供者。请参考它们以获取更简洁的说明,但大致步骤如下:
您可能有多个状态,例如data
和isLoading
,以等待某些API进程。该模型本身扩展了ChangeNotifier
。
这可以是Consumer
或Selector
。
对于状态模型,该类看起来或多或少如下。请注意notifyListeners
,它会广播更改。
class DataState extends ChangeNotifier{
bool isLoading;
Data data;
Future loadData(){
isLoading = true;
notifyListeners();
service.get().then((newData){
isLoading = false;
data = newData;
notifyListeners();
});
}
}
现在是小部件。这将是非常简单的代码。
return ChangeNotifierProvider(
create: (_) => DataState()..loadData(),
child: ...{
Selector<DataState, bool>(
selector: (context, model) => model.isLoading,
builder: (context, isLoading, _) {
if (isLoading) {
return ProgressBar;
}
return Container(
child: Consumer<DataState>(builder: (context, dataState, child) {
return WidgetData(...);
}
));
},
),
}
);
状态模型的实例由ChangeNotifierProvider提供。选择器和消费者监视状态,分别为isLoading
和data
的状态。有not much difference between them,但个人使用方式将取决于其构建器提供的内容。消费者提供对状态模型的访问权限,因此对于直接在其下的任何小部件调用loadData
都很简单。
如果没有,则可以使用Provider.of
。如果我们想在从第二个屏幕返回时刷新页面,则可以执行以下操作:
await Navigator.push(context,
MaterialPageRoute(
builder: (_) {
return Screen2();
));
Provider.of<DataState>(context, listen: false).loadData();
答案 15 :(得分:0)
为我工作:
...
onPressed: (){pushUpdate('/somePageName');}
...
pushUpdate (string pageName) async { //in the same class
await pushPage(context, pageName);
setState(() {});
}
//---------------------------------------------
//general sub
pushPage (context, namePage) async {
await Navigator.pushNamed(context, namePage);
}
在这种情况下,弹出的方式(在UI中带有按钮或在android中为“后退”)都无关紧要。
答案 16 :(得分:0)
您可以使用pushReplacement并指定新的路线
答案 17 :(得分:0)
今天,我遇到了同样的情况,但是我设法以更简单的方式解决了它,我只是定义了一个全局变量,该变量在第一个有状态类中使用,当我导航到第二个有状态小部件时,我让它更新了值全局变量的值,它会自动强制第一个窗口小部件更新。这是一个示例(我匆忙编写了它,所以我没有放置脚手架或材料应用程序,我只是想说明我的观点):
import 'package:flutter/material.dart';
int count = 0 ;
class FirstPage extends StatefulWidget {
FirstPage({Key key}) : super(key: key);
@override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
@override
Widget build(BuildContext context) {
return InkWell(
onTap(){
Navigator.of(context).push(MaterialPageRoute(builder: (context) =>
new SecondPage());
},
child: Text('First', style : TextStyle(fontSize: count == 0 ? 20.0 : 12.0)),
),
}
class SecondPage extends StatefulWidget {
SecondPage({Key key}) : super(key: key);
@override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
@override
Widget build(BuildContext context) {
return IconButton(
icon: new Icon(Icons.add),
color: Colors.amber,
iconSize: 15.0,
onPressed: (){
count++ ;
},
),
}
答案 18 :(得分:0)
我遇到了类似的问题。
请试试这个:
在第一页:
Navigator.push( context, MaterialPageRoute( builder: (context) => SecondPage()), ).then((value) => setState(() {}));
从 SecondPage() 返回到 FirstPage() 后,“then”语句将运行并刷新页面。