如何在 Flutter 中设置 Firebase Analytics 自定义事件而不在每个屏幕中传递“分析/观察者”对象

May*_*ate 7 google-analytics firebase flutter firebase-analytics bloc

我正在为我的 Flutter 项目设置Firebase 分析包。库中提供的示例传递analytics用于跟踪事件和observer跟踪选项卡更改的对象。

class MyApp extends StatelessWidget {
 ...
Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Firebase Analytics Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      navigatorObservers: <NavigatorObserver>[observer],
      home: MyHomePage(
        title: 'Firebase Analytics Demo',
        analytics: analytics,
        observer: observer,
      ),
    );
  }
}

...

class _MyHomePageState extends State<MyHomePage> {
...
Future<void> _sendAnalyticsEvent() async {
    await analytics.logEvent(
      name: 'test_event',
      parameters: <String, dynamic>{
        'string': 'string',
        'int': 42,
        'long': 12345678910,
        'double': 42.0,
        'bool': true,
      },
    );
    setMessage('logEvent succeeded');
  }
...
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序由许多屏幕组成,其中状态通过Bloc包进行管理。将这些对象从mainScreen发生事件的树中一路向下传递是不好的。

有没有办法访问它们而无需在小部件树周围传递它们。或者,如果我创建类的新对象FirebaseAnalytics并使用生成的对象来设置事件,它会起作用吗?

static FirebaseAnalytics analytics = FirebaseAnalytics();

还是应该使用 Flutter_Bloc 作为记录和设置 Flutter 事件的中心位置?

Mar*_*yns 13

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',
            ),
        ),
    ); 
  }
}
Run Code Online (Sandbox Code Playgroud)

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');
  }
Run Code Online (Sandbox Code Playgroud)

Now you don't need to pass your Firebase instances to the widget constructors.


小智 6

还可以创建包含所有全局实例的文件。例如:lib目录中的文件: globals.dart

文件内容:

class Global {
    static final FirebaseAnalytics analytics = FirebaseAnalytics();
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

Global.analytics.logEvent(...)
Run Code Online (Sandbox Code Playgroud)


Mat*_*ias 5

除了使用提供程序或具有静态参数的全局类之外,另一种选择是servicesGetIt包一起使用。

只需创建一个包含analyticsand 的类observer。例如像这样:

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
}
Run Code Online (Sandbox Code Playgroud)

现在创建一个locator并将该类注册为一个 lazy singleton

GetIt locator = GetIt.instance;

setupServiceLocator() {
  locator.registerLazySingleton<AnalyticsService>(() => AnalyticsService());
}
Run Code Online (Sandbox Code Playgroud)

使可locator访问:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  setupServiceLocator();
  runApp(MyApp());
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以service通过调用locator. 例如:

return MaterialApp(
  debugShowCheckedModeBanner: false,
  title: 'Demo',
  theme: themeData,
  initialRoute: SplashScreen.id,
  routes: routes,
  navigatorObservers: [
    // Access the observer
    locator<AnalyticsService>().getAnalyticsObserver(),
  ],
);
Run Code Online (Sandbox Code Playgroud)

}

或者

 onTap: () {
   locator<AnalyticsService>().logScreens(name: DetailsScreen.id);
 }
Run Code Online (Sandbox Code Playgroud)