Flutter:从另一个 class 将 BuildContext 设置为 null
Flutter: Setting BuildContext to null from another class
我想知道如何使另一个 class 中的 BuildContext
无效,以防止它在处理上下文的小部件后被异步函数使用。
我假设它是通过引用传递的,所以我尝试在原始小部件中将它设置为 null
(在我的用例中,我在 dispose 方法中将它设置为 null
并且onWillPop
方法,两者都无济于事)。我为我想做的事情创建了一个简单的示例应用程序。如您所见,如果您 运行 应用程序,则上下文未设置为 null
。
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Setting BuildContext to null',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Setting BuildContext to null'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
AsyncClass _asyncClass = AsyncClass();
Duration duration = const Duration(seconds: 5);
void toggleContext(BuildContext context){
Timer.periodic(duration, (_){
print("Setting context to null");
context = null;
});
}
@override
Widget build(BuildContext context) {
toggleContext(context);
_asyncClass.asyncFunc(context);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(),
);
}
}
class AsyncClass{
void asyncFunc(BuildContext context){
const duration = const Duration(seconds: 1);
Timer.periodic(duration, (_){
if(context==null){
print("Context is null");
} else {
print("Context is not null");
}
});
}
}
asyncFunc
中的 context
只是对 Dart 堆上原始 BuildContext
对象的引用的副本,因此将 context
设置为 null 只会设置那个特定变量为 null,而不是所有具有相同引用的变量。
如果您来自 C/C++ 背景,您所做的更像是更改指针的地址值,而不是更改指针指向的地址处的值.
编辑: 一个潜在的解决方案是做这样的事情:
class AsyncClass{
BuildContext context;
void asyncFunc(BuildContext param){
context = param;
const duration = const Duration(seconds: 1);
Timer.periodic(duration, (_){
if(context==null){
print("Context is null");
} else {
print("Context is not null");
}
});
}
}
然后这样做:
void toggleContext(BuildContext context){
Timer.periodic(duration, (_){
print("Setting context to null");
_asyncClass.context = null;
});
}
我发现我可以使用 ValueParameter
class 来包装 BuildContext
对象。这使我可以非常简单地将新的 ValueParameter
值传递给函数,并很容易地从它包含的任何函数中将它们全部设置为 null
。
这是我的解决方案(我添加了 if(_timer==null)
以防止在应用程序刷新时形成重复的 Timer
)。
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Setting BuildContext to null',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Setting BuildContext to null'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
AsyncClass _asyncClass = AsyncClass();
Duration duration = const Duration(seconds: 5);
Timer _timer;
void toggleContext(ValueNotifier context) {
if (_timer == null)
_timer = Timer.periodic(duration, (_) {
print("Setting context to null");
context.value = null;
});
}
@override
Widget build(BuildContext param) {
ValueNotifier context = ValueNotifier(param);
toggleContext(context);
_asyncClass.asyncFunc(context);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(),
);
}
}
class AsyncClass {
Timer _timer;
void asyncFunc(ValueNotifier context) {
const duration = const Duration(seconds: 1);
if (_timer == null)
_timer = Timer.periodic(duration, (_) {
if (context.value == null) {
print("Context is null");
} else {
print("Context is not null");
}
});
}
}
我想知道如何使另一个 class 中的 BuildContext
无效,以防止它在处理上下文的小部件后被异步函数使用。
我假设它是通过引用传递的,所以我尝试在原始小部件中将它设置为 null
(在我的用例中,我在 dispose 方法中将它设置为 null
并且onWillPop
方法,两者都无济于事)。我为我想做的事情创建了一个简单的示例应用程序。如您所见,如果您 运行 应用程序,则上下文未设置为 null
。
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Setting BuildContext to null',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Setting BuildContext to null'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
AsyncClass _asyncClass = AsyncClass();
Duration duration = const Duration(seconds: 5);
void toggleContext(BuildContext context){
Timer.periodic(duration, (_){
print("Setting context to null");
context = null;
});
}
@override
Widget build(BuildContext context) {
toggleContext(context);
_asyncClass.asyncFunc(context);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(),
);
}
}
class AsyncClass{
void asyncFunc(BuildContext context){
const duration = const Duration(seconds: 1);
Timer.periodic(duration, (_){
if(context==null){
print("Context is null");
} else {
print("Context is not null");
}
});
}
}
asyncFunc
中的 context
只是对 Dart 堆上原始 BuildContext
对象的引用的副本,因此将 context
设置为 null 只会设置那个特定变量为 null,而不是所有具有相同引用的变量。
如果您来自 C/C++ 背景,您所做的更像是更改指针的地址值,而不是更改指针指向的地址处的值.
编辑: 一个潜在的解决方案是做这样的事情:
class AsyncClass{
BuildContext context;
void asyncFunc(BuildContext param){
context = param;
const duration = const Duration(seconds: 1);
Timer.periodic(duration, (_){
if(context==null){
print("Context is null");
} else {
print("Context is not null");
}
});
}
}
然后这样做:
void toggleContext(BuildContext context){
Timer.periodic(duration, (_){
print("Setting context to null");
_asyncClass.context = null;
});
}
我发现我可以使用 ValueParameter
class 来包装 BuildContext
对象。这使我可以非常简单地将新的 ValueParameter
值传递给函数,并很容易地从它包含的任何函数中将它们全部设置为 null
。
这是我的解决方案(我添加了 if(_timer==null)
以防止在应用程序刷新时形成重复的 Timer
)。
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Setting BuildContext to null',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Setting BuildContext to null'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
AsyncClass _asyncClass = AsyncClass();
Duration duration = const Duration(seconds: 5);
Timer _timer;
void toggleContext(ValueNotifier context) {
if (_timer == null)
_timer = Timer.periodic(duration, (_) {
print("Setting context to null");
context.value = null;
});
}
@override
Widget build(BuildContext param) {
ValueNotifier context = ValueNotifier(param);
toggleContext(context);
_asyncClass.asyncFunc(context);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(),
);
}
}
class AsyncClass {
Timer _timer;
void asyncFunc(ValueNotifier context) {
const duration = const Duration(seconds: 1);
if (_timer == null)
_timer = Timer.periodic(duration, (_) {
if (context.value == null) {
print("Context is null");
} else {
print("Context is not null");
}
});
}
}