186 lines
5.7 KiB
Dart
186 lines
5.7 KiB
Dart
import 'package:autosos_flutter/service/background_service.dart';
|
||
import 'package:autosos_flutter/service/location_service.dart';
|
||
import 'package:autosos_flutter/service/push_service.dart';
|
||
import 'package:autosos_flutter/util/toast.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
|
||
/// 性能优化页(对应 Android OptimizationActivity)
|
||
/// 检查并展示:定位 / 推送 / 后台 / 心跳 / 网络 各模块状态
|
||
class OptimizationPage extends ConsumerStatefulWidget {
|
||
const OptimizationPage({super.key});
|
||
|
||
@override
|
||
ConsumerState<OptimizationPage> createState() => _OptimizationPageState();
|
||
}
|
||
|
||
class _OptimizationPageState extends ConsumerState<OptimizationPage> {
|
||
bool _locating = false;
|
||
String? _lastLoc;
|
||
String? _cid;
|
||
bool _bgRunning = false;
|
||
bool _heartbeat = false;
|
||
int _online = 0;
|
||
bool _testing = false;
|
||
String? _netResult;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_refresh();
|
||
}
|
||
|
||
Future<void> _refresh() async {
|
||
final loc = LocationService.instance.last;
|
||
final bg = await BackgroundService.instance.isRunning();
|
||
setState(() {
|
||
_cid = PushService.instance.clientId;
|
||
_bgRunning = bg;
|
||
_lastLoc = loc == null
|
||
? null
|
||
: '(${(loc['latitude'] as num? ?? 0).toDouble().toStringAsFixed(4)}, ${(loc['longitude'] as num? ?? 0).toDouble().toStringAsFixed(4)})';
|
||
});
|
||
}
|
||
|
||
Future<void> _fetchOnce() async {
|
||
setState(() => _locating = true);
|
||
try {
|
||
final loc = await LocationService.instance.fetchOnce();
|
||
if (loc == null) {
|
||
Toast.error('定位失败');
|
||
} else {
|
||
setState(() {
|
||
_lastLoc =
|
||
'(${(loc['latitude'] as num? ?? 0).toDouble().toStringAsFixed(4)}, ${(loc['longitude'] as num? ?? 0).toDouble().toStringAsFixed(4)})';
|
||
});
|
||
}
|
||
} catch (e) {
|
||
Toast.error('定位异常:$e');
|
||
} finally {
|
||
if (mounted) setState(() => _locating = false);
|
||
}
|
||
}
|
||
|
||
Future<void> _testNet() async {
|
||
setState(() {
|
||
_testing = true;
|
||
_netResult = null;
|
||
});
|
||
final sw = Stopwatch()..start();
|
||
try {
|
||
final r = await LocationService.instance.fetchOnce();
|
||
sw.stop();
|
||
if (r != null) {
|
||
setState(() {
|
||
_netResult = '定位耗时 ${sw.elapsedMilliseconds} ms';
|
||
});
|
||
Toast.success('网络正常');
|
||
} else {
|
||
setState(() {
|
||
_netResult = '定位失败';
|
||
});
|
||
}
|
||
} catch (e) {
|
||
sw.stop();
|
||
setState(() {
|
||
_netResult = '异常:$e';
|
||
});
|
||
} finally {
|
||
if (mounted) setState(() => _testing = false);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: AppBar(title: const Text('性能优化')),
|
||
body: ListView(
|
||
children: [
|
||
_section('定位服务'),
|
||
ListTile(
|
||
leading: const Icon(Icons.location_on, color: Colors.red),
|
||
title: const Text('当前位置'),
|
||
subtitle: Text(_lastLoc ?? '尚未获取'),
|
||
trailing: _locating
|
||
? const SizedBox(
|
||
width: 16,
|
||
height: 16,
|
||
child: CircularProgressIndicator(strokeWidth: 2),
|
||
)
|
||
: const Icon(Icons.refresh),
|
||
onTap: _fetchOnce,
|
||
),
|
||
_section('推送服务'),
|
||
ListTile(
|
||
leading: const Icon(Icons.notifications, color: Colors.red),
|
||
title: const Text('个推 CID'),
|
||
subtitle: Text(_cid ?? '未初始化'),
|
||
),
|
||
_section('后台保活'),
|
||
ListTile(
|
||
leading: Icon(
|
||
Icons.alarm_on,
|
||
color: _bgRunning ? Colors.green : Colors.grey,
|
||
),
|
||
title: const Text('Background Service'),
|
||
subtitle: Text(_bgRunning ? '运行中' : '未运行'),
|
||
trailing: TextButton(
|
||
onPressed: () async {
|
||
if (_bgRunning) {
|
||
await BackgroundService.instance.stop();
|
||
} else {
|
||
await BackgroundService.instance.start();
|
||
}
|
||
_refresh();
|
||
},
|
||
child: Text(_bgRunning ? '停止' : '启动'),
|
||
),
|
||
),
|
||
_section('心跳 / 网络'),
|
||
ListTile(
|
||
leading: const Icon(Icons.favorite, color: Colors.red),
|
||
title: const Text('心跳'),
|
||
subtitle: Text(_heartbeat ? '正常' : '—'),
|
||
trailing: Text('${_online}s'),
|
||
),
|
||
ListTile(
|
||
leading: const Icon(Icons.network_check, color: Colors.red),
|
||
title: const Text('网络测试'),
|
||
subtitle: Text(_netResult ?? '点击测试'),
|
||
trailing: _testing
|
||
? const SizedBox(
|
||
width: 16,
|
||
height: 16,
|
||
child: CircularProgressIndicator(strokeWidth: 2),
|
||
)
|
||
: const Icon(Icons.play_arrow),
|
||
onTap: _testing ? null : _testNet,
|
||
),
|
||
_section('开发者'),
|
||
ListTile(
|
||
title: const Text('强制重连推送'),
|
||
onTap: () async {
|
||
PushService.instance.init();
|
||
_refresh();
|
||
Toast.success('已重连');
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _section(String title) => Container(
|
||
color: Colors.grey.shade100,
|
||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
||
width: double.infinity,
|
||
child: Text(
|
||
title,
|
||
style: const TextStyle(
|
||
fontSize: 12,
|
||
color: Colors.grey,
|
||
),
|
||
),
|
||
);
|
||
}
|