fix: 修复手机连不上服务器时启动页无限转圈(B-58)
- 启动页先读本地凭证:无凭证(首次打开)直接进登录页,不再先等 SDK 初始化 - SDK init/login 加 20s 超时;init 用共享 Future 防止超时后重复触发 initSDK - 登录页对 IM 登录超时给出明确提示(确认手机连着公司内网 WiFi) - 修复 flutter create 模板遗留的 widget_test(引用不存在的 MyApp),改为登录页渲染冒烟测试 - 版本号 1.0.1+2
This commit is contained in:
+12
-6
@@ -77,18 +77,24 @@ class _SplashGateState extends State<SplashGate> {
|
|||||||
|
|
||||||
Future<void> _boot() async {
|
Future<void> _boot() async {
|
||||||
final im = IMService.instance;
|
final im = IMService.instance;
|
||||||
try {
|
// 先读本地凭证:没有凭证(首次打开)直接去登录页,
|
||||||
await im.init();
|
// 不在启动页等 SDK 初始化——服务器连不上时 initSDK 可能长时间不返回,
|
||||||
|
// 不能让启动页一直转圈。
|
||||||
final credential = await LoginScreen.readCredential();
|
final credential = await LoginScreen.readCredential();
|
||||||
if (credential != null) {
|
if (credential == null) {
|
||||||
await im.login(userID: credential.$1, token: credential.$2);
|
if (!mounted) return;
|
||||||
|
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => const LoginScreen()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await im.init().timeout(const Duration(seconds: 20));
|
||||||
|
await im.login(userID: credential.$1, token: credential.$2).timeout(const Duration(seconds: 20));
|
||||||
CallService.instance.start();
|
CallService.instance.start();
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => const HomeScreen()));
|
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => const HomeScreen()));
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// 自动登录失败(token 失效等):清凭证回登录页
|
// 自动登录失败(token 失效、服务器连不上等):清凭证回登录页
|
||||||
await LoginScreen.clearCredential();
|
await LoginScreen.clearCredential();
|
||||||
}
|
}
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|||||||
@@ -78,8 +78,11 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
password: password,
|
password: password,
|
||||||
platformID: IMService.instance.platformID,
|
platformID: IMService.instance.platformID,
|
||||||
);
|
);
|
||||||
// 2. 登录 OpenIM SDK
|
// 2. 登录 OpenIM SDK(服务器连不上时这一步可能长时间不返回,加超时兜底)
|
||||||
await IMService.instance.login(userID: result.userID, token: result.token);
|
await IMService.instance.login(userID: result.userID, token: result.token).timeout(
|
||||||
|
const Duration(seconds: 20),
|
||||||
|
onTimeout: () => throw AuthException('连不上消息服务器,请确认手机连着公司内网 WiFi'),
|
||||||
|
);
|
||||||
// 3. 启动通话信令监听
|
// 3. 启动通话信令监听
|
||||||
CallService.instance.start();
|
CallService.instance.start();
|
||||||
// 4. 存凭证用于下次自动登录
|
// 4. 存凭证用于下次自动登录
|
||||||
|
|||||||
@@ -75,9 +75,24 @@ class IMService extends ChangeNotifier {
|
|||||||
|
|
||||||
int get platformID => Platform.isIOS ? IMPlatform.ios : IMPlatform.android;
|
int get platformID => Platform.isIOS ? IMPlatform.ios : IMPlatform.android;
|
||||||
|
|
||||||
/// App 启动时初始化 SDK(只做一次)
|
/// App 启动时初始化 SDK(只做一次)。
|
||||||
Future<void> init() async {
|
/// 用共享 Future 防止超时后重复触发 initSDK:第一次调用还在跑时,
|
||||||
if (sdkReady) return;
|
/// 后续调用直接复用同一个 Future;失败了则允许下次重试。
|
||||||
|
Future<void>? _initFuture;
|
||||||
|
|
||||||
|
Future<void> init() {
|
||||||
|
if (sdkReady) return Future.value();
|
||||||
|
final inFlight = _initFuture;
|
||||||
|
if (inFlight != null) return inFlight;
|
||||||
|
final future = _doInit();
|
||||||
|
_initFuture = future;
|
||||||
|
return future.whenComplete(() {
|
||||||
|
// 失败的初始化允许重试;成功的保留 sdkReady 标记即可
|
||||||
|
if (!sdkReady && identical(_initFuture, future)) _initFuture = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _doInit() async {
|
||||||
final dir = await getApplicationDocumentsDirectory();
|
final dir = await getApplicationDocumentsDirectory();
|
||||||
final dataDir = '${dir.path}/openim';
|
final dataDir = '${dir.path}/openim';
|
||||||
await Directory(dataDir).create(recursive: true);
|
await Directory(dataDir).create(recursive: true);
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
name: changlian
|
name: changlian
|
||||||
description: 畅联 —— 公司内部通讯 App(手机端)
|
description: 畅联 —— 公司内部通讯 App(手机端)
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.0.0+1
|
version: 1.0.1+2
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.6.0 <4.0.0"
|
sdk: ">=3.6.0 <4.0.0"
|
||||||
|
|||||||
@@ -1,30 +1,11 @@
|
|||||||
// This is a basic Flutter widget test.
|
import 'package:changlian/screens/login_screen.dart';
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'package:changlian/main.dart';
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
testWidgets('登录页能正常渲染', (tester) async {
|
||||||
// Build our app and trigger a frame.
|
await tester.pumpWidget(const MaterialApp(home: LoginScreen()));
|
||||||
await tester.pumpWidget(const MyApp());
|
expect(find.text('畅联'), findsOneWidget);
|
||||||
|
expect(find.text('登录'), findsOneWidget);
|
||||||
// Verify that our counter starts at 0.
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsNothing);
|
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
|
||||||
expect(find.text('0'), findsNothing);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user