handleClassEnd method
切换入口:preparing → switching → (retrying)* → idle / failed。
返回 true 表示切换流程已接管;返回 false 表示调用方应继续原有结束课堂流程。
event 仅作日志/扩展占位,当前未使用。
Implementation
Future<bool> handleClassEnd(Object? event) async {
final env = _env;
if (env == null) return false;
if (status.value.state != SwitchState.idle) return false;
if (!env.classSwitchEnabled()) return false;
final from = env.currentClassId().trim();
final next = env.nextClassId()?.trim();
if (next == null || next.isEmpty) return false;
if (next == from) return false;
// preparing
status.value = status.value.copyWith(
state: SwitchState.preparing,
currentClassId: from,
targetClassId: next,
retryCount: 0,
clearError: true,
);
_cancelled = false;
// switching(首次)
status.value = status.value.copyWith(state: SwitchState.switching);
final firstErr = await _tryPerform(env, next);
if (firstErr == null) {
status.value = status.value.copyWith(
state: SwitchState.idle,
currentClassId: next,
clearError: true,
);
return true;
}
if (shouldFallbackToClassEnd(firstErr)) {
reset();
return false;
}
if (!firstErr.retryable) {
return _markFailedAndFallback(firstErr);
}
if (_cancelled) {
_markFailed(firstErr);
return true;
}
// 重试循环(最多 maxRetry 次)
ClassSwitchError lastErr = firstErr;
for (int i = 1; i <= maxRetry; i++) {
if (_cancelled) {
_markFailed(lastErr);
return true;
}
await Future.delayed(retryDelay);
if (_cancelled) {
_markFailed(lastErr);
return true;
}
status.value = status.value.copyWith(
state: SwitchState.retrying,
retryCount: i,
errorCode: lastErr.code,
errorMessage: lastErr.message,
);
final err = await _tryPerform(env, next);
if (err == null) {
status.value = status.value.copyWith(
state: SwitchState.idle,
currentClassId: next,
clearError: true,
);
return true;
}
if (shouldFallbackToClassEnd(err)) {
reset();
return false;
}
lastErr = err;
if (!err.retryable) {
return _markFailedAndFallback(err);
}
}
return _markFailedAndFallback(lastErr);
}