How to set Firebase Analytics custom events in Flutter without passing 'analytics/observer' object in each screen
You can use the provider
package to 'provide' both your analytics and observer down your widget tree.
class MyApp extends StatelessWidget {
static FirebaseAnalytics analytics = FirebaseAnalytics();
static FirebaseAnalyticsObserver observer =
FirebaseAnalyticsObserver(analytics: analytics);
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<FirebaseAnalytics>.value(value: analytics),
Provider<FirebaseAnalyticsObserver>.value(value: observer),
],
child: MaterialApp(
title: 'Firebase Analytics Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
navigatorObservers: <NavigatorObserver>[observer],
home: MyHomePage(
title: 'Firebase Analytics Demo',
),
),
);
}
}
Then in any of your child widgets...
Future<void> _sendAnalyticsEvent() async {
FirebaseAnalytics analytics = Provider.of<FirebaseAnalytics>(context);
await analytics.logEvent(
name: 'test_event',
parameters: <String, dynamic>{
'string': 'string',
'int': 42,
'long': 12345678910,
'double': 42.0,
'bool': true,
},
);
setMessage('logEvent succeeded');
}
Now you don't need to pass your Firebase instances to the widget constructors.
It is also possible to create a file with all of your global instances. e.g: file: globals.dart in your lib directory.
Content of the file:
class Global {
static final FirebaseAnalytics analytics = FirebaseAnalytics();
}
Then to use it:
Global.analytics.logEvent(...)
Besides using provider or a global class with static parameters, another option is to use services
with the GetIt package.
Just create a class that hold's the analytics
and observer
. E.g. like this:
class AnalyticsService {
final FirebaseAnalytics _analytics = FirebaseAnalytics();
FirebaseAnalyticsObserver getAnalyticsObserver() => FirebaseAnalyticsObserver(analytics: _analytics);
Future logScreens({@required String name}) async {
await _analytics.setCurrentScreen(screenName: name);
}
... // implement the events you want to track
}
Now create a locator
and register the class as a lazy singleton
:
GetIt locator = GetIt.instance;
setupServiceLocator() {
locator.registerLazySingleton<AnalyticsService>(() => AnalyticsService());
}
Make the locator
accessable:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
setupServiceLocator();
runApp(MyApp());
}
Now you can access the service
from everywhere in your app by calling the locator
.
For example:
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Demo',
theme: themeData,
initialRoute: SplashScreen.id,
routes: routes,
navigatorObservers: [
// Access the observer
locator<AnalyticsService>().getAnalyticsObserver(),
],
);
}
or
onTap: () {
locator<AnalyticsService>().logScreens(name: DetailsScreen.id);
}