我有一个main.dart,中间有一个按钮。当用户点击按钮时,它将导航到home.dart页面。我的home.dart页面的中心还有一个按钮,当用户单击该按钮时,它会导航到详细信息页面。应用程序树和代码如下所示。
我尝试在home.dart中实现“ InheritedWidget” ,因此在home.dart之后,我可以调用“ void _handleUserInteraction” 函数使用“ InheritedWidget”。不幸的是,我不断收到错误消息:
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.google.ar.sceneform:plugin:1.6.0'
}
home.dart代码:
I/flutter (20715): The getter 'handleOnTap' was called on null.
I/flutter (20715): Receiver: null
I/flutter (20715): Tried calling: handleOnTap
details.dart代码:
import 'package:flutter/material.dart';
import 'dart:async';
import 'main.dart';
import 'details.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Timer timer;
// TODO: 1 - INIT STATE
@override
void initState() {
super.initState();
setState(() {
_initializeTimer();
});
}
// TODO: 3 - INITIALIZE TIMER
void _initializeTimer() {
timer = Timer.periodic(const Duration(minutes: 5), (__) {
_logOutUser();
});
}
// TODO: 4 - LOG OUT USER
void _logOutUser() {
timer.cancel();
Navigator.push(
context, new MaterialPageRoute(builder: (context) => new MyApp()));
}
// TODO: 5 - HANDLE USER INTERACTION
// void _handleUserInteraction([_]) {
void _handleUserInteraction() {
print("+++++++ _handleUserInteraction Header ++++++++");
if (!timer.isActive) {
return;
}
timer.cancel();
_initializeTimer();
print("+++++++ _handleUserInteraction Footer ++++++++");
}
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData(
primarySwatch: Colors.red,
),
home: LoginState(
callback: _handleUserInteraction,
child: Builder(builder: homeScreenBuilder)),
);
}
@override
Widget homeScreenBuilder(BuildContext context) {
Function() _callback = LoginState.of(context).callback;
return GestureDetector(
onTap: _callback,
onDoubleTap: _callback,
onLongPress: _callback,
onTapCancel: _callback,
child: new Scaffold(
appBar: AppBar(
title: Text("HOME PAGE"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'GOTO DETAILS PAGE',
),
new RaisedButton(
child: new Text("Details"),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new Details()));
})
],
),
),
));
}
class LoginState extends InheritedWidget {
final Widget child;
final Function() callback;
final Key key;
LoginState({@required this.callback, @required this.child, this.key})
: super(key: key);
@override
bool updateShouldNotify(LoginState oldWidget) {
return true;
}
static LoginState of(BuildContext context) =>
context.inheritFromWidgetOfExactType(LoginState);
}
更新: 我更改了home.dart代码。 onTap:_callback正常运行,但在details.dart中,我得到了同样的错误:
错误:-调用getter的“回调”为null。
答案 0 :(得分:0)
您收到错误 The getter 'callback' was called on null.
的原因是因为 LoginState.of(context)
为空。
class _DetailsState extends State<Details> {
@override
Widget build(BuildContext context) {
Function() _callback = LoginState.of(context).callback;
...
}
}
由于您正在使用 InheritedWidget
,我假设您可能正在尝试进行状态管理。如果是这样,您可以查看有关实施应用状态管理的 guide。一种方法是使用 provider
。
您可以尝试运行下面的示例。我是根据给定的样本得出的。
main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'dart:async';
import 'details.dart';
void main() {
// https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple#changenotifierprovider
runApp(ChangeNotifierProvider(
create: (context) => LoginState(),
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
// This allows access to LoginState data if no UI changes needed
// https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple#providerof
Provider.of<LoginState>(context, listen: false).initializeTimer();
}
@override
Widget build(BuildContext context) {
// Consumer grants access to LoginState
// https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple#consumer
return Consumer<LoginState>(
builder: (context, loginState, child) {
return GestureDetector(
onTap: () => loginState.handleUserInteraction(),
// onDoubleTap: _callback,
// onLongPress: _callback,
// onTapCancel: _callback,
child: new Scaffold(
appBar: AppBar(
title: Text("HOME PAGE"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'GOTO DETAILS PAGE',
),
new RaisedButton(
child: new Text("Details"),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new Details()));
})
],
),
),
));
},
);
}
}
// https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple#changenotifier
class LoginState extends ChangeNotifier {
Timer _timer;
void initializeTimer() {
_timer = Timer.periodic(const Duration(minutes: 5), (__) {
logOutUser();
});
}
void logOutUser() {
_timer.cancel();
}
void handleUserInteraction() {
print("+++++++ _handleUserInteraction Header ++++++++");
if (!_timer.isActive) {
return;
}
_timer.cancel();
initializeTimer();
print("+++++++ _handleUserInteraction Footer ++++++++");
}
}
详细信息.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'main.dart';
class Details extends StatefulWidget {
@override
_DetailsState createState() => _DetailsState();
}
class _DetailsState extends State<Details> {
@override
Widget build(BuildContext context) {
return Consumer<LoginState>(
builder: (context, loginState, child) {
return GestureDetector(
onTap: () => loginState.handleUserInteraction(),
// onDoubleTap: _callback,
// onLongPress: _callback,
// onTapCancel: _callback,
child: new Scaffold(
appBar: AppBar(
title: Text("Details PAGE"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Every time Tabed it reset the home timer',
),
],
),
),
));
},
);
}
}