我正在尝试使用Firebase分析来跟踪用户导航并按下一些按钮,我创建了一个_currentScreen()
函数,我在用户导航到的类中调用了init状态 这是函数
Future<Null> _currentScreen() async {
await widget.analytics.setCurrentScreen(
screenName: 'second screen view', screenClassOverride: 'SecondScreenView');
}
我做了另一个_sendAnalytics函数,当用户单击按钮时,我会调用它;这是函数:
Future<Null> _sendAnalytics() async {
await widget.analytics
.logEvent(name: 'launchhhh', parameters: <String, dynamic>{});
}
我有几个问题: 1st-在第二个屏幕类的初始化状态中,它警告:is方法覆盖在"State"中注释为@mustCallSuper的方法,但不调用重写的方法。 2nd-当我运行代码并按下导航按钮时,我有这个
[ERROR:flutter/shell/common/shell.cc(181)] Dart Error: Unhandled exception:
E/flutter (12744): NoSuchMethodError: The method 'logEvent' was called on null.
E/flutter (12744): Receiver: null
E/flutter (12744): Tried calling: logEvent(name: "launchhhh", parameters: _LinkedHashMap len:0)
E/flutter (12744): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
E/flutter (12744): #1 FirstScreenState._sendAnalytics (file:///C:/Users/pc/Desktop/wedn2/wedn2/lib/h.dart:40:10)
3-另外,当我评论_sendanalytics功能时
NoSuchMethodError: The method 'setCurrentScreen' was called on null.
E/flutter (15612): Receiver: null
E/flutter (15612): Tried calling: setCurrentScreen(screenClassOverride: "SecondScreenView", screenName: "second screen view")
E/flutter (15612): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
E/flutter (15612): #1 SecondScreenState._currentScreen (file:///C:/Users/pc/Desktop/wedn2/wedn2/lib/h.dart:91:28)
E/flutter (15612): <asynchronous suspension>
E/flutter (15612): #2 SecondScreenState.initState (file:///C:/Users/pc/Desktop/wedn2/wedn2/lib/h.dart:88:5)
E/flutter (15612): #3 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3787:58)
E/flutter (15612): #4 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3653:5)
我不知道问题在哪里有任何帮助?这是我的整个代码:
import 'package:flutter/material.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_analytics/observer.dart';
import 'dart:async';
class MyAppf extends StatelessWidget {
static FirebaseAnalytics analytics = new FirebaseAnalytics();
static FirebaseAnalyticsObserver observer =
new FirebaseAnalyticsObserver(analytics: analytics);
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
navigatorObservers: <NavigatorObserver>[observer],
// home: new WallScreen(analytics: analytics, observer: observer),
home: new FirstScreen(),
);
}
}
class FirstScreen extends StatefulWidget {
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
FirstScreen({this.analytics, this.observer});
@override
FirstScreenState createState() => new FirstScreenState();
}
class FirstScreenState extends State<FirstScreen> {
Future<Null> _sendAnalytics() async {
await widget.analytics
.logEvent(name: 'launchhhh', parameters: <String, dynamic>{});
}
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
FirstScreenState({this.analytics, this.observer});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Launch screen'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
_sendAnalytics();
},
),
),
);
}
}
class SecondScreen extends StatefulWidget {
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
SecondScreen({this.analytics, this.observer});
@override
SecondScreenState createState() => new SecondScreenState();
}
class SecondScreenState extends State<SecondScreen> {
@override
void initState() {
_currentScreen();
}
Future<Null> _currentScreen() async {
await widget.analytics.setCurrentScreen(
screenName: 'second screen view', screenClassOverride: 'SecondScreenView');
}
Future<Null> _sendAnalyticsback() async {
await widget.analytics
.logEvent(name: 'back', parameters: <String, dynamic>{});
}
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
SecondScreenState({this.analytics, this.observer});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
_sendAnalyticsback();
},
child: Text('Go back!'),
),
),
);
}
}
编辑我把我的变量分析传递给小部件
home:new FirstScreen(analytics: analytics),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen(analytics:analytics)),
而不是:
home:new FirstScreen(),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
但仍然是调用 null 的相同错误
您需要将变量分析传递给您的小部件。
new FirstScreen(),
new SecondScreen(),
应该是 :
new FirstScreen(analytics: analytics),
new SecondScreen(analytics: analytics),
不要使用静态成员,因为它们旨在通过类本身进行访问。您尝试执行的操作的一种更精细的方法是将MyApp
声明为SatetfulWidget
,现在您analytics
并且observer
可以是State
类的私有成员并使用initState
来初始化它们,请参阅以下示例:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
FirebaseAnalytics _analytics;
FirebaseAnalyticsObserver _observer ;
@override
void initState() {
_analytics = FirebaseAnalytics();
_observer = FirebaseAnalyticsObserver(analytics: _analytics);
super.initState();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
如果要保留小部件Stateless
可以在构造函数的初始值设定项列表中初始化observer
,这需要在创建MyApp
时向analytics
字段传递一个值MyApp(analytics:FirebaseAnalytics())
:
class MyApp extends StatelessWidget {
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
MyApp({Key key,@required this.analytics})
: observer = FirebaseAnalyticsObserver(analytics: analytics),
super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}