如何在不在每个屏幕中传递 'analytics/observer' 对象的情况下在 Flutter 中设置 Firebase Analytics 自定义事件

How to set Firebase Analytics custom events in Flutter without passing 'analytics/observer' object in each screen

我正在设置 Firebase Analytics Package for my Flutter project. The sample 库中提供的传递 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');
  }
...
}

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

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

static FirebaseAnalytics analytics = FirebaseAnalytics();

或者我应该使用 Flutter_Bloc 作为记录和设置我的 Flutter 事件的中心位置吗?

您可以使用 provider 包来 'provide' 您的分析和观察者在您的小部件树下。

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',
            ),
        ),
    ); 
  }
}

然后在您的任何子窗口小部件中...

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');
  }

现在您不需要将 Firebase 实例传递给小部件构造函数。

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

文件内容:

class Global {
    static final FirebaseAnalytics analytics = FirebaseAnalytics();
}

然后使用它:

Global.analytics.logEvent(...)

除了使用 provider or a global class with static parameters, another option is to use services with the GetIt 包。

只需创建一个包含 analyticsobserver 的 class。例如。像这样:

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
}

现在创建一个 locator 并将 class 注册为惰性 singleton:

GetIt locator = GetIt.instance;

setupServiceLocator() {
  locator.registerLazySingleton<AnalyticsService>(() => AnalyticsService());
}

使 locator 可访问:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  setupServiceLocator();
  runApp(MyApp());
}

现在您可以通过调用 locator 从应用程序的任何位置访问 service。 例如:

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

}

 onTap: () {
   locator<AnalyticsService>().logScreens(name: DetailsScreen.id);
 }