yx_tracking_flutter/lib/yx_tracking_flutter.dart

160 lines
4.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:yx_tracking_flutter/src/config/analytics_config.dart';
import 'package:yx_tracking_flutter/src/core/analytics_core.dart';
import 'package:yx_tracking_flutter/src/core/interceptors.dart';
import 'package:yx_tracking_flutter/src/model/device_info.dart';
import 'package:yx_tracking_flutter/src/model/recent_event_summary.dart';
import 'package:yx_tracking_flutter/src/model/user_info.dart';
export 'src/config/analytics_config.dart';
export 'src/core/interceptors.dart';
export 'src/model/device_info.dart';
export 'src/model/event.dart';
export 'src/model/recent_event_summary.dart';
export 'src/model/user_info.dart';
/// 对外唯一入口Facade
class Analytics {
/// 私有构造,避免外部实例化。
Analytics._();
/// 获取一个实例(用于满足 lint 对构造器的要求)。
factory Analytics.instance() => Analytics._();
static AnalyticsCore _core = AnalyticsCore();
static _AnalyticsLifecycleObserver? _lifecycleObserver;
@visibleForTesting
/// 测试钩子:读取当前核心实现。
static AnalyticsCore get coreForTesting => _core;
@visibleForTesting
/// 测试钩子:覆盖内部核心实现。
static set coreForTesting(AnalyticsCore core) => _core = core;
/// 初始化 SDK。
static Future<void> init(AnalyticsConfig config) => _core.init(config);
/// 记录事件。
static Future<void> track(
String eventType, {
Map<String, dynamic>? eventParams,
Map<String, dynamic>? customTags,
int? timestamp,
}) {
return _core.track(
eventType,
eventParams: eventParams,
customTags: customTags,
timestamp: timestamp,
);
}
/// 设置用户信息。
static Future<void> setUser(UserInfo? userInfo) => _core.setUser(userInfo);
/// 覆盖设备信息。
static Future<void> setDeviceInfo(DeviceInfo deviceInfo) =>
_core.setDeviceInfo(deviceInfo);
/// 触发一次上报。
static Future<void> flush({bool force = false}) => _core.flush(force: force);
/// 当前本地缓存事件数量(用于调试/演示)。
static Future<int> cachedEventCount() => _core.cachedEventCount();
/// 最近事件摘要(用于调试面板)。
static Future<List<RecentEventSummary>> cachedRecentEvents({
int limit = 20,
}) =>
_core.cachedRecentEvents(limit: limit);
/// Phase 2手动触发一次配置刷新默认强制刷新
static Future<void> refreshConfig({bool force = true}) =>
_core.refreshConfig(force: force);
/// Phase 3立即上报一次 SDK 指标(调试/测试用)。
static Future<void> reportMetricsNow() => _core.reportMetricsNow();
/// Phase 3注册事件拦截器。
static void addInterceptor(AnalyticsInterceptor interceptor) {
_core.addInterceptor(interceptor);
}
/// 动态设置 Debug 开关。
static void setDebug({required bool enabled}) {
unawaited(_core.setDebug(enabled: enabled));
}
/// 可选:当宿主确定不再需要 SDK 时调用。
static Future<void> dispose() async {
unbindLifecycleObserver();
await _core.dispose();
}
/// 可选:绑定应用生命周期监听,进入后台时自动 flush。
static void bindLifecycleObserver({
bool flushOnBackground = true,
bool flushOnDetached = true,
}) {
if (_lifecycleObserver != null) {
return;
}
WidgetsFlutterBinding.ensureInitialized();
final observer = _AnalyticsLifecycleObserver(
flushOnBackground: flushOnBackground,
flushOnDetached: flushOnDetached,
onFlush: () {
unawaited(_core.flush(force: true));
},
);
_lifecycleObserver = observer;
WidgetsBinding.instance.addObserver(observer);
}
/// 解绑生命周期监听,避免重复注册或泄漏。
static void unbindLifecycleObserver() {
final observer = _lifecycleObserver;
if (observer == null) {
return;
}
WidgetsBinding.instance.removeObserver(observer);
_lifecycleObserver = null;
}
}
class _AnalyticsLifecycleObserver extends WidgetsBindingObserver {
_AnalyticsLifecycleObserver({
required this.flushOnBackground,
required this.flushOnDetached,
required this.onFlush,
});
final bool flushOnBackground;
final bool flushOnDetached;
final VoidCallback onFlush;
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.hidden:
if (flushOnBackground) {
onFlush();
}
case AppLifecycleState.detached:
if (flushOnDetached) {
onFlush();
}
case AppLifecycleState.resumed:
break;
}
}
}