939 lines
28 KiB
Markdown
939 lines
28 KiB
Markdown
|
# 阿里百炼模型网络错误处理与自动重连机制设计文档
|
|||
|
|
|||
|
## 1. 概述
|
|||
|
|
|||
|
本设计文档旨在解决阿里百炼模型在使用过程中遇到网络错误后无法继续工作的问题。当前系统在`onErrorReceived`回调被触发后,没有实现错误恢复机制,且缺乏网络状态监听和自动重连功能。本文档将设计一个完整的网络错误处理和自动重连机制,确保在断网或网络不稳定情况下系统能够自动恢复连接。
|
|||
|
|
|||
|
## 2. 系统架构
|
|||
|
|
|||
|
```mermaid
|
|||
|
graph TD
|
|||
|
A[阿里百炼AI对话系统] --> B[网络状态监听器]
|
|||
|
A --> C[错误处理模块]
|
|||
|
C --> D[重连管理器]
|
|||
|
D --> E[连接状态管理器]
|
|||
|
B --> D
|
|||
|
D --> A
|
|||
|
```
|
|||
|
|
|||
|
## 3. 当前问题分析
|
|||
|
|
|||
|
### 3.1 现有问题
|
|||
|
1. 当前系统在收到`onErrorReceived`回调后,没有实现错误恢复机制
|
|||
|
2. 缺乏网络状态监听功能,无法检测到网络断开
|
|||
|
3. 没有自动重连机制,在网络恢复后无法自动重新连接
|
|||
|
|
|||
|
### 3.2 核心问题代码分析
|
|||
|
在`MainActivity.java`中,当前的错误处理实现如下:
|
|||
|
```java
|
|||
|
@Override
|
|||
|
public void onErrorReceived(@NonNull TYError errorInfo) {
|
|||
|
Log.e(TAG_AI, "收到错误: " + errorInfo);
|
|||
|
//appendLogMessage("错误: " + errorInfo.getMessage());
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 4. 设计方案
|
|||
|
|
|||
|
### 4.1 网络状态监听器设计
|
|||
|
|
|||
|
#### 4.1.1 网络状态监听器类
|
|||
|
创建`NetworkStateManager`类,用于监听网络连接状态变化:
|
|||
|
|
|||
|
```java
|
|||
|
public class NetworkStateManager {
|
|||
|
private ConnectivityManager connectivityManager;
|
|||
|
private ConnectivityManager.NetworkCallback networkCallback;
|
|||
|
private NetworkStateListener stateListener;
|
|||
|
private boolean isNetworkAvailable = false;
|
|||
|
private Context context;
|
|||
|
|
|||
|
public interface NetworkStateListener {
|
|||
|
void onNetworkAvailable();
|
|||
|
void onNetworkLost();
|
|||
|
}
|
|||
|
|
|||
|
public NetworkStateManager(Context context) {
|
|||
|
this.context = context.getApplicationContext();
|
|||
|
this.connectivityManager = (ConnectivityManager)
|
|||
|
context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|||
|
}
|
|||
|
|
|||
|
public void setNetworkStateListener(NetworkStateListener listener) {
|
|||
|
this.stateListener = listener;
|
|||
|
}
|
|||
|
|
|||
|
public boolean isNetworkAvailable() {
|
|||
|
return isNetworkAvailable;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 4.1.2 网络状态回调实现
|
|||
|
```java
|
|||
|
public void registerNetworkCallback() {
|
|||
|
NetworkRequest networkRequest = new NetworkRequest.Builder()
|
|||
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
|||
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
|||
|
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
|||
|
.build();
|
|||
|
|
|||
|
networkCallback = new ConnectivityManager.NetworkCallback() {
|
|||
|
@Override
|
|||
|
public void onAvailable(Network network) {
|
|||
|
super.onAvailable(network);
|
|||
|
isNetworkAvailable = true;
|
|||
|
Log.d("NetworkState", "网络连接已恢复");
|
|||
|
if (stateListener != null) {
|
|||
|
stateListener.onNetworkAvailable();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onLost(Network network) {
|
|||
|
super.onLost(network);
|
|||
|
isNetworkAvailable = false;
|
|||
|
Log.d("NetworkState", "网络连接已断开");
|
|||
|
if (stateListener != null) {
|
|||
|
stateListener.onNetworkLost();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onUnavailable() {
|
|||
|
super.onUnavailable();
|
|||
|
isNetworkAvailable = false;
|
|||
|
Log.d("NetworkState", "网络连接不可用");
|
|||
|
if (stateListener != null) {
|
|||
|
stateListener.onNetworkLost();
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
|
|||
|
}
|
|||
|
|
|||
|
public void unregisterNetworkCallback() {
|
|||
|
if (networkCallback != null && connectivityManager != null) {
|
|||
|
try {
|
|||
|
connectivityManager.unregisterNetworkCallback(networkCallback);
|
|||
|
} catch (Exception e) {
|
|||
|
Log.e("NetworkState", "注销网络回调失败", e);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 4.2 错误处理模块设计
|
|||
|
|
|||
|
#### 4.2.1 错误类型定义
|
|||
|
```java
|
|||
|
public enum NetworkErrorType {
|
|||
|
NETWORK_DISCONNECTED, // 网络断开
|
|||
|
CONNECTION_TIMEOUT, // 连接超时
|
|||
|
SERVER_ERROR, // 服务器错误
|
|||
|
AUTHENTICATION_FAILED, // 认证失败
|
|||
|
UNKNOWN_ERROR // 未知错误
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 4.2.2 错误处理管理器
|
|||
|
```java
|
|||
|
public class NetworkErrorHandler {
|
|||
|
private static final int MAX_RETRY_ATTEMPTS = 3;
|
|||
|
private static final long RETRY_DELAY_MS = 5000;
|
|||
|
|
|||
|
private int retryCount = 0;
|
|||
|
private Handler handler;
|
|||
|
private Runnable retryRunnable;
|
|||
|
private ErrorCallback errorCallback;
|
|||
|
|
|||
|
public interface ErrorCallback {
|
|||
|
void onRetryAttempt(int attempt);
|
|||
|
void onMaxRetriesReached();
|
|||
|
}
|
|||
|
|
|||
|
public NetworkErrorHandler(Looper looper) {
|
|||
|
this.handler = new Handler(looper);
|
|||
|
}
|
|||
|
|
|||
|
public void setErrorCallback(ErrorCallback callback) {
|
|||
|
this.errorCallback = callback;
|
|||
|
}
|
|||
|
|
|||
|
public void handleNetworkError(TYError error) {
|
|||
|
if (retryCount < MAX_RETRY_ATTEMPTS) {
|
|||
|
scheduleRetry();
|
|||
|
} else {
|
|||
|
if (errorCallback != null) {
|
|||
|
errorCallback.onMaxRetriesReached();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void scheduleRetry() {
|
|||
|
retryCount++;
|
|||
|
if (errorCallback != null) {
|
|||
|
errorCallback.onRetryAttempt(retryCount);
|
|||
|
}
|
|||
|
|
|||
|
retryRunnable = () -> {
|
|||
|
// 触发重连逻辑
|
|||
|
};
|
|||
|
|
|||
|
long delay = RETRY_DELAY_MS * retryCount; // 指数退避
|
|||
|
handler.postDelayed(retryRunnable, delay);
|
|||
|
}
|
|||
|
|
|||
|
public void reset() {
|
|||
|
retryCount = 0;
|
|||
|
if (retryRunnable != null) {
|
|||
|
handler.removeCallbacks(retryRunnable);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 4.3 重连管理器设计
|
|||
|
|
|||
|
#### 4.3.1 重连策略
|
|||
|
1. 指数退避重连策略
|
|||
|
2. 最大重试次数限制
|
|||
|
3. 网络状态检测
|
|||
|
|
|||
|
#### 4.3.2 重连管理器类
|
|||
|
```java
|
|||
|
public class ReconnectionManager {
|
|||
|
private static final int MAX_RECONNECT_ATTEMPTS = 5;
|
|||
|
private static final long INITIAL_DELAY_MS = 2000;
|
|||
|
private static final long MAX_DELAY_MS = 30000;
|
|||
|
|
|||
|
private int reconnectAttempts = 0;
|
|||
|
private boolean isReconnecting = false;
|
|||
|
private Handler handler;
|
|||
|
private ReconnectCallback reconnectCallback;
|
|||
|
|
|||
|
public interface ReconnectCallback {
|
|||
|
void onReconnectAttempt(int attempt);
|
|||
|
void onReconnectSuccess();
|
|||
|
void onReconnectFailed();
|
|||
|
}
|
|||
|
|
|||
|
public ReconnectionManager(Looper looper) {
|
|||
|
this.handler = new Handler(looper);
|
|||
|
}
|
|||
|
|
|||
|
public void setReconnectCallback(ReconnectCallback callback) {
|
|||
|
this.reconnectCallback = callback;
|
|||
|
}
|
|||
|
|
|||
|
public boolean isReconnecting() {
|
|||
|
return isReconnecting;
|
|||
|
}
|
|||
|
|
|||
|
public void scheduleReconnection(Runnable reconnectTask) {
|
|||
|
if (isReconnecting || reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
isReconnecting = true;
|
|||
|
reconnectAttempts++;
|
|||
|
|
|||
|
if (reconnectCallback != null) {
|
|||
|
reconnectCallback.onReconnectAttempt(reconnectAttempts);
|
|||
|
}
|
|||
|
|
|||
|
// 计算延迟时间(指数退避)
|
|||
|
long delay = Math.min(INITIAL_DELAY_MS * (1L << (reconnectAttempts - 1)), MAX_DELAY_MS);
|
|||
|
|
|||
|
handler.postDelayed(() -> {
|
|||
|
if (reconnectTask != null) {
|
|||
|
reconnectTask.run();
|
|||
|
}
|
|||
|
}, delay);
|
|||
|
}
|
|||
|
|
|||
|
public void onReconnectSuccess() {
|
|||
|
isReconnecting = false;
|
|||
|
reconnectAttempts = 0;
|
|||
|
if (reconnectCallback != null) {
|
|||
|
reconnectCallback.onReconnectSuccess();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void onReconnectFailed() {
|
|||
|
isReconnecting = false;
|
|||
|
if (reconnectCallback != null) {
|
|||
|
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|||
|
reconnectCallback.onReconnectFailed();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void reset() {
|
|||
|
isReconnecting = false;
|
|||
|
reconnectAttempts = 0;
|
|||
|
// 移除所有待处理的回调
|
|||
|
handler.removeCallbacksAndMessages(null);
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 5. 核心功能实现
|
|||
|
|
|||
|
### 5.1 网络状态监听实现
|
|||
|
|
|||
|
#### 5.1.1 初始化网络监听
|
|||
|
在`MainActivity`中添加网络状态监听初始化:
|
|||
|
|
|||
|
```java
|
|||
|
// 在MainActivity中添加成员变量
|
|||
|
private NetworkStateManager networkStateManager;
|
|||
|
private NetworkErrorHandler networkErrorHandler;
|
|||
|
private ReconnectionManager reconnectionManager;
|
|||
|
|
|||
|
// 在onCreate方法中初始化
|
|||
|
private void initNetworkComponents() {
|
|||
|
// 初始化网络状态管理器
|
|||
|
networkStateManager = new NetworkStateManager(this);
|
|||
|
networkStateManager.setNetworkStateListener(new NetworkStateManager.NetworkStateListener() {
|
|||
|
@Override
|
|||
|
public void onNetworkAvailable() {
|
|||
|
runOnUiThread(() -> handleNetworkAvailable());
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onNetworkLost() {
|
|||
|
runOnUiThread(() -> handleNetworkLoss());
|
|||
|
}
|
|||
|
});
|
|||
|
networkStateManager.registerNetworkCallback();
|
|||
|
|
|||
|
// 初始化错误处理器
|
|||
|
networkErrorHandler = new NetworkErrorHandler(getMainLooper());
|
|||
|
networkErrorHandler.setErrorCallback(new NetworkErrorHandler.ErrorCallback() {
|
|||
|
@Override
|
|||
|
public void onRetryAttempt(int attempt) {
|
|||
|
Log.d(TAG_AI, "第" + attempt + "次重试");
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onMaxRetriesReached() {
|
|||
|
Log.e(TAG_AI, "达到最大重试次数");
|
|||
|
// 显示错误提示给用户
|
|||
|
runOnUiThread(() -> showNetworkErrorDialog());
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// 初始化重连管理器
|
|||
|
reconnectionManager = new ReconnectionManager(getMainLooper());
|
|||
|
reconnectionManager.setReconnectCallback(new ReconnectionManager.ReconnectCallback() {
|
|||
|
@Override
|
|||
|
public void onReconnectAttempt(int attempt) {
|
|||
|
Log.d(TAG_AI, "第" + attempt + "次重连尝试");
|
|||
|
currentState = DialogState.DIALOG_RECONNECTING;
|
|||
|
runOnUiThread(() -> updateUIState());
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onReconnectSuccess() {
|
|||
|
Log.d(TAG_AI, "重连成功");
|
|||
|
currentState = DialogState.DIALOG_LISTENING;
|
|||
|
runOnUiThread(() -> {
|
|||
|
updateUIState();
|
|||
|
hideNetworkErrorDialog();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
public void onReconnectFailed() {
|
|||
|
Log.e(TAG_AI, "重连失败");
|
|||
|
currentState = DialogState.DIALOG_ERROR;
|
|||
|
runOnUiThread(() -> {
|
|||
|
updateUIState();
|
|||
|
showNetworkErrorDialog();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 5.1.2 网络状态回调处理
|
|||
|
```java
|
|||
|
private void handleNetworkAvailable() {
|
|||
|
Log.d(TAG_AI, "网络连接已恢复");
|
|||
|
// 如果之前处于错误状态,尝试重连
|
|||
|
if (currentState == DialogState.DIALOG_ERROR) {
|
|||
|
scheduleReconnection();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void handleNetworkLoss() {
|
|||
|
Log.d(TAG_AI, "网络连接已断开");
|
|||
|
// 暂停当前对话,等待网络恢复
|
|||
|
if (currentState != DialogState.DIALOG_IDLE &&
|
|||
|
currentState != DialogState.DIALOG_ERROR) {
|
|||
|
currentState = DialogState.DIALOG_ERROR;
|
|||
|
updateUIState();
|
|||
|
// 显示网络断开提示
|
|||
|
showNetworkDisconnectDialog();
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 5.2 错误处理实现
|
|||
|
|
|||
|
#### 5.2.1 改进的错误处理回调
|
|||
|
```java
|
|||
|
@Override
|
|||
|
public void onErrorReceived(@NonNull TYError errorInfo) {
|
|||
|
Log.e(TAG_AI, "收到错误: " + errorInfo);
|
|||
|
|
|||
|
// 记录错误信息
|
|||
|
lastError = errorInfo;
|
|||
|
DialogState previousState = currentState;
|
|||
|
currentState = DialogState.DIALOG_ERROR;
|
|||
|
|
|||
|
// 更新UI状态
|
|||
|
runOnUiThread(() -> {
|
|||
|
updateUIState();
|
|||
|
showNetworkErrorDialog();
|
|||
|
});
|
|||
|
|
|||
|
// 根据错误类型处理
|
|||
|
handleNetworkError(errorInfo);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 5.2.2 错误分类处理
|
|||
|
```java
|
|||
|
private void handleNetworkError(TYError errorInfo) {
|
|||
|
String errorMessage = errorInfo.getMessage();
|
|||
|
|
|||
|
if (errorMessage != null) {
|
|||
|
if (errorMessage.contains("网络") ||
|
|||
|
errorMessage.contains("连接") ||
|
|||
|
errorMessage.contains("Network")) {
|
|||
|
// 网络相关错误
|
|||
|
Log.d(TAG_AI, "处理网络相关错误");
|
|||
|
networkErrorHandler.handleNetworkError(errorInfo);
|
|||
|
// 调度重连
|
|||
|
scheduleReconnection();
|
|||
|
} else if (errorMessage.contains("超时") ||
|
|||
|
errorMessage.contains("timeout")) {
|
|||
|
// 超时错误
|
|||
|
Log.d(TAG_AI, "处理超时错误");
|
|||
|
networkErrorHandler.handleNetworkError(errorInfo);
|
|||
|
// 调度重连
|
|||
|
scheduleReconnection();
|
|||
|
} else {
|
|||
|
// 其他错误
|
|||
|
Log.d(TAG_AI, "处理其他错误");
|
|||
|
networkErrorHandler.handleNetworkError(errorInfo);
|
|||
|
}
|
|||
|
} else {
|
|||
|
// 未知错误
|
|||
|
networkErrorHandler.handleNetworkError(errorInfo);
|
|||
|
scheduleReconnection();
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 5.3 自动重连实现
|
|||
|
|
|||
|
#### 5.3.1 重连调度器
|
|||
|
```java
|
|||
|
private void scheduleReconnection() {
|
|||
|
if (reconnectionManager.isReconnecting()) {
|
|||
|
Log.d(TAG_AI, "重连已在进行中");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Log.d(TAG_AI, "调度重连任务");
|
|||
|
reconnectionManager.scheduleReconnection(this::reconnectToService);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### 5.3.2 服务重连实现
|
|||
|
```java
|
|||
|
private void reconnectToService() {
|
|||
|
Log.d(TAG_AI, "开始重连到阿里百炼服务");
|
|||
|
|
|||
|
runOnUiThread(() -> {
|
|||
|
// 显示重连进度
|
|||
|
showReconnectionDialog();
|
|||
|
|
|||
|
// 在后台线程执行重连
|
|||
|
new Thread(() -> {
|
|||
|
try {
|
|||
|
// 销毁旧的对话实例
|
|||
|
if (multiModalDialog != null) {
|
|||
|
multiModalDialog.destroy();
|
|||
|
multiModalDialog = null;
|
|||
|
}
|
|||
|
|
|||
|
// 延迟一小段时间确保资源释放
|
|||
|
Thread.sleep(500);
|
|||
|
|
|||
|
// 重新初始化SDK
|
|||
|
initializeParams();
|
|||
|
|
|||
|
// 重新创建对话实例
|
|||
|
runOnUiThread(() -> {
|
|||
|
createConversation();
|
|||
|
|
|||
|
// 延迟启动对话
|
|||
|
handler.postDelayed(() -> {
|
|||
|
startConversation();
|
|||
|
// 通知重连管理器重连成功
|
|||
|
reconnectionManager.onReconnectSuccess();
|
|||
|
}, 1000);
|
|||
|
});
|
|||
|
|
|||
|
} catch (Exception e) {
|
|||
|
Log.e(TAG_AI, "重连失败", e);
|
|||
|
runOnUiThread(() -> {
|
|||
|
// 通知重连管理器重连失败
|
|||
|
reconnectionManager.onReconnectFailed();
|
|||
|
hideReconnectionDialog();
|
|||
|
});
|
|||
|
}
|
|||
|
}).start();
|
|||
|
});
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 6. 状态管理
|
|||
|
|
|||
|
### 6.1 对话状态扩展
|
|||
|
```java
|
|||
|
public enum DialogState {
|
|||
|
DIALOG_IDLE, // 空闲状态
|
|||
|
DIALOG_CONNECTING, // 连接中
|
|||
|
DIALOG_LISTENING, // 监听中
|
|||
|
DIALOG_SPEAKING, // 说话中
|
|||
|
DIALOG_THINKING, // 思考中
|
|||
|
DIALOG_ERROR, // 错误状态
|
|||
|
DIALOG_RECONNECTING // 重连中
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 6.2 状态转换图
|
|||
|
```mermaid
|
|||
|
stateDiagram-v2
|
|||
|
[*] --> DIALOG_IDLE
|
|||
|
DIALOG_IDLE --> DIALOG_CONNECTING: 启动对话
|
|||
|
DIALOG_CONNECTING --> DIALOG_LISTENING: 连接成功
|
|||
|
DIALOG_LISTENING --> DIALOG_THINKING: 收到语音
|
|||
|
DIALOG_THINKING --> DIALOG_SPEAKING: 收到回复
|
|||
|
DIALOG_SPEAKING --> DIALOG_LISTENING: 播放完成
|
|||
|
DIALOG_CONNECTING --> DIALOG_ERROR: 连接失败
|
|||
|
DIALOG_LISTENING --> DIALOG_ERROR: 网络错误
|
|||
|
DIALOG_ERROR --> DIALOG_RECONNECTING: 网络恢复/手动重连
|
|||
|
DIALOG_RECONNECTING --> DIALOG_CONNECTING: 重连成功
|
|||
|
DIALOG_RECONNECTING --> DIALOG_ERROR: 重连失败
|
|||
|
```
|
|||
|
|
|||
|
## 7. 配置参数
|
|||
|
|
|||
|
### 7.1 重连配置
|
|||
|
```xml
|
|||
|
<!-- 网络重连配置 -->
|
|||
|
<resources>
|
|||
|
<integer name="max_reconnect_attempts">5</integer>
|
|||
|
<integer name="initial_reconnect_delay_ms">2000</integer>
|
|||
|
<integer name="max_reconnect_delay_ms">30000</integer>
|
|||
|
<integer name="network_check_interval_ms">5000</integer>
|
|||
|
<integer name="max_retry_attempts">3</integer>
|
|||
|
<integer name="retry_delay_ms">5000</integer>
|
|||
|
</resources>
|
|||
|
```
|
|||
|
|
|||
|
### 7.2 从资源文件读取配置
|
|||
|
```java
|
|||
|
private void loadNetworkConfig() {
|
|||
|
Resources res = getResources();
|
|||
|
ReconnectionManager.MAX_RECONNECT_ATTEMPTS =
|
|||
|
res.getInteger(R.integer.max_reconnect_attempts);
|
|||
|
ReconnectionManager.INITIAL_DELAY_MS =
|
|||
|
res.getInteger(R.integer.initial_reconnect_delay_ms);
|
|||
|
ReconnectionManager.MAX_DELAY_MS =
|
|||
|
res.getInteger(R.integer.max_reconnect_delay_ms);
|
|||
|
NetworkErrorHandler.MAX_RETRY_ATTEMPTS =
|
|||
|
res.getInteger(R.integer.max_retry_attempts);
|
|||
|
NetworkErrorHandler.RETRY_DELAY_MS =
|
|||
|
res.getInteger(R.integer.retry_delay_ms);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 8. 测试方案
|
|||
|
|
|||
|
### 8.1 单元测试
|
|||
|
1. 网络状态监听测试
|
|||
|
- 模拟网络断开和恢复事件
|
|||
|
- 验证回调函数正确执行
|
|||
|
2. 错误处理逻辑测试
|
|||
|
- 测试不同类型错误的处理
|
|||
|
- 验证重试机制
|
|||
|
3. 重连机制测试
|
|||
|
- 测试指数退避算法
|
|||
|
- 验证最大重试次数限制
|
|||
|
|
|||
|
### 8.2 集成测试
|
|||
|
1. 模拟网络断开/恢复场景
|
|||
|
- 在对话过程中断开网络
|
|||
|
- 恢复网络后验证自动重连
|
|||
|
2. 验证自动重连功能
|
|||
|
- 测试不同错误情况下的重连
|
|||
|
- 验证重连成功后的对话继续
|
|||
|
3. 测试对话流程的连续性
|
|||
|
- 验证重连后对话状态正确恢复
|
|||
|
- 确保用户体验不受影响
|
|||
|
|
|||
|
## 9. 安全考虑
|
|||
|
|
|||
|
1. 网络状态变化时的数据保护
|
|||
|
- 确保敏感数据不因网络中断而泄露
|
|||
|
- 实现数据持久化存储
|
|||
|
2. 重连过程中的认证信息保护
|
|||
|
- 避免认证信息在日志中明文输出
|
|||
|
- 使用安全的认证机制
|
|||
|
3. 错误日志中的敏感信息过滤
|
|||
|
- 过滤日志中的API密钥等敏感信息
|
|||
|
- 实现日志级别控制
|
|||
|
|
|||
|
## 10. 性能优化
|
|||
|
|
|||
|
1. 避免频繁重连导致的资源消耗
|
|||
|
- 实现合理的重连间隔
|
|||
|
- 限制并发重连任务
|
|||
|
2. 网络状态监听的性能优化
|
|||
|
- 减少不必要的网络状态检查
|
|||
|
- 优化回调处理逻辑
|
|||
|
3. 合理的重连间隔设置
|
|||
|
- 使用指数退避算法
|
|||
|
- 根据网络状况动态调整
|
|||
|
|
|||
|
## 11. UI/UX 设计
|
|||
|
|
|||
|
### 11.1 网络状态指示器
|
|||
|
```java
|
|||
|
private void updateNetworkStatusIndicator() {
|
|||
|
if (networkStateManager != null) {
|
|||
|
boolean isAvailable = networkStateManager.isNetworkAvailable();
|
|||
|
// 更新UI上的网络状态图标
|
|||
|
runOnUiThread(() -> {
|
|||
|
if (networkStatusIcon != null) {
|
|||
|
networkStatusIcon.setImageResource(
|
|||
|
isAvailable ? R.drawable.ic_network_connected :
|
|||
|
R.drawable.ic_network_disconnected);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 11.2 用户提示
|
|||
|
1. 网络断开提示
|
|||
|
2. 重连进度显示
|
|||
|
3. 重连成功/失败通知
|
|||
|
4. 手动重连按钮
|
|||
|
|
|||
|
### 11.3 对话框实现示例
|
|||
|
```java
|
|||
|
private void showNetworkErrorDialog() {
|
|||
|
if (networkErrorDialog != null && networkErrorDialog.isShowing()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|||
|
builder.setTitle("网络连接错误")
|
|||
|
.setMessage("与阿里百炼服务器的连接已断开,请检查网络设置")
|
|||
|
.setPositiveButton("重试", (dialog, which) -> {
|
|||
|
// 手动触发重连
|
|||
|
scheduleReconnection();
|
|||
|
dialog.dismiss();
|
|||
|
})
|
|||
|
.setNegativeButton("取消", (dialog, which) -> {
|
|||
|
dialog.dismiss();
|
|||
|
});
|
|||
|
|
|||
|
networkErrorDialog = builder.create();
|
|||
|
networkErrorDialog.setCancelable(false);
|
|||
|
networkErrorDialog.show();
|
|||
|
}
|
|||
|
|
|||
|
private void showReconnectionDialog() {
|
|||
|
if (reconnectionDialog != null && reconnectionDialog.isShowing()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|||
|
builder.setTitle("正在重新连接")
|
|||
|
.setMessage("正在尝试重新连接到阿里百炼服务器...")
|
|||
|
.setView(new ProgressBar(this))
|
|||
|
.setCancelable(false);
|
|||
|
|
|||
|
reconnectionDialog = builder.create();
|
|||
|
reconnectionDialog.show();
|
|||
|
}
|
|||
|
|
|||
|
private void hideReconnectionDialog() {
|
|||
|
if (reconnectionDialog != null && reconnectionDialog.isShowing()) {
|
|||
|
reconnectionDialog.dismiss();
|
|||
|
reconnectionDialog = null;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 12. 生命周期管理
|
|||
|
|
|||
|
### 12.1 Activity生命周期处理
|
|||
|
```java
|
|||
|
@Override
|
|||
|
protected void onResume() {
|
|||
|
super.onResume();
|
|||
|
// 重新注册网络监听
|
|||
|
if (networkStateManager != null) {
|
|||
|
networkStateManager.registerNetworkCallback();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
protected void onPause() {
|
|||
|
super.onPause();
|
|||
|
// 注销网络监听
|
|||
|
if (networkStateManager != null) {
|
|||
|
networkStateManager.unregisterNetworkCallback();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
protected void onDestroy() {
|
|||
|
super.onDestroy();
|
|||
|
// 清理资源
|
|||
|
cleanupNetworkComponents();
|
|||
|
}
|
|||
|
|
|||
|
private void cleanupNetworkComponents() {
|
|||
|
if (networkStateManager != null) {
|
|||
|
networkStateManager.unregisterNetworkCallback();
|
|||
|
networkStateManager = null;
|
|||
|
}
|
|||
|
|
|||
|
if (reconnectionManager != null) {
|
|||
|
reconnectionManager.reset();
|
|||
|
reconnectionManager = null;
|
|||
|
}
|
|||
|
|
|||
|
if (networkErrorHandler != null) {
|
|||
|
networkErrorHandler.reset();
|
|||
|
networkErrorHandler = null;
|
|||
|
}
|
|||
|
|
|||
|
// 清理对话框
|
|||
|
if (networkErrorDialog != null && networkErrorDialog.isShowing()) {
|
|||
|
networkErrorDialog.dismiss();
|
|||
|
networkErrorDialog = null;
|
|||
|
}
|
|||
|
|
|||
|
if (reconnectionDialog != null && reconnectionDialog.isShowing()) {
|
|||
|
reconnectionDialog.dismiss();
|
|||
|
reconnectionDialog = null;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 13. 监控和日志
|
|||
|
|
|||
|
### 13.1 网络状态监控
|
|||
|
```java
|
|||
|
public class NetworkMonitor {
|
|||
|
private static final String TAG = "NetworkMonitor";
|
|||
|
private long lastNetworkLostTime = 0;
|
|||
|
private long lastNetworkAvailableTime = 0;
|
|||
|
private int networkLostCount = 0;
|
|||
|
|
|||
|
public void onNetworkLost() {
|
|||
|
lastNetworkLostTime = System.currentTimeMillis();
|
|||
|
networkLostCount++;
|
|||
|
Log.d(TAG, "网络断开次数: " + networkLostCount);
|
|||
|
}
|
|||
|
|
|||
|
public void onNetworkAvailable() {
|
|||
|
lastNetworkAvailableTime = System.currentTimeMillis();
|
|||
|
long downtime = lastNetworkAvailableTime - lastNetworkLostTime;
|
|||
|
Log.d(TAG, "网络恢复,断网时长: " + downtime + "ms");
|
|||
|
}
|
|||
|
|
|||
|
public NetworkStats getNetworkStats() {
|
|||
|
return new NetworkStats(networkLostCount,
|
|||
|
System.currentTimeMillis() - lastNetworkLostTime);
|
|||
|
}
|
|||
|
|
|||
|
public static class NetworkStats {
|
|||
|
private int disconnectCount;
|
|||
|
private long lastDowntime;
|
|||
|
|
|||
|
public NetworkStats(int disconnectCount, long lastDowntime) {
|
|||
|
this.disconnectCount = disconnectCount;
|
|||
|
this.lastDowntime = lastDowntime;
|
|||
|
}
|
|||
|
|
|||
|
// Getters...
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 14. 扩展功能
|
|||
|
|
|||
|
### 14.1 网络质量检测
|
|||
|
```java
|
|||
|
public class NetworkQualityChecker {
|
|||
|
private ConnectivityManager connectivityManager;
|
|||
|
|
|||
|
public NetworkQuality getNetworkQuality() {
|
|||
|
Network network = connectivityManager.getActiveNetwork();
|
|||
|
if (network == null) {
|
|||
|
return NetworkQuality.DISCONNECTED;
|
|||
|
}
|
|||
|
|
|||
|
NetworkCapabilities capabilities =
|
|||
|
connectivityManager.getNetworkCapabilities(network);
|
|||
|
if (capabilities == null) {
|
|||
|
return NetworkQuality.UNKNOWN;
|
|||
|
}
|
|||
|
|
|||
|
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
|||
|
return NetworkQuality.WIFI;
|
|||
|
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
|
|||
|
// 检查蜂窝网络类型
|
|||
|
return getCellularNetworkQuality(capabilities);
|
|||
|
}
|
|||
|
|
|||
|
return NetworkQuality.UNKNOWN;
|
|||
|
}
|
|||
|
|
|||
|
private NetworkQuality getCellularNetworkQuality(NetworkCapabilities capabilities) {
|
|||
|
if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
|
|||
|
return NetworkQuality.WIFI;
|
|||
|
} else if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
|
|||
|
return NetworkQuality.CELLULAR_4G;
|
|||
|
}
|
|||
|
return NetworkQuality.CELLULAR_3G;
|
|||
|
}
|
|||
|
|
|||
|
public enum NetworkQuality {
|
|||
|
DISCONNECTED, UNKNOWN, CELLULAR_3G, CELLULAR_4G, WIFI
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 14.2 智能重连策略
|
|||
|
```java
|
|||
|
public class SmartReconnectStrategy {
|
|||
|
private NetworkQualityChecker qualityChecker;
|
|||
|
private NetworkMonitor networkMonitor;
|
|||
|
|
|||
|
public long calculateReconnectDelay(int attempt, NetworkErrorType errorType) {
|
|||
|
// 基础延迟
|
|||
|
long baseDelay = 2000L * (1L << Math.min(attempt, 4)); // 指数退避
|
|||
|
|
|||
|
// 根据网络质量调整
|
|||
|
NetworkQualityChecker.NetworkQuality quality = qualityChecker.getNetworkQuality();
|
|||
|
switch (quality) {
|
|||
|
case DISCONNECTED:
|
|||
|
return baseDelay * 2; // 网络断开时增加延迟
|
|||
|
case CELLULAR_3G:
|
|||
|
return baseDelay * 1.5; // 3G网络增加延迟
|
|||
|
case CELLULAR_4G:
|
|||
|
case WIFI:
|
|||
|
return baseDelay; // 正常延迟
|
|||
|
default:
|
|||
|
return baseDelay;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public boolean shouldReconnect(NetworkErrorType errorType) {
|
|||
|
// 根据错误类型和网络统计决定是否重连
|
|||
|
NetworkMonitor.NetworkStats stats = networkMonitor.getNetworkStats();
|
|||
|
|
|||
|
// 如果断开次数过多,可能需要用户干预
|
|||
|
if (stats.getDisconnectCount() > 10) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// 某些错误类型不需要自动重连
|
|||
|
switch (errorType) {
|
|||
|
case AUTHENTICATION_FAILED:
|
|||
|
return false; // 认证失败需要用户处理
|
|||
|
default:
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 15. 部署和配置
|
|||
|
|
|||
|
### 15.1 配置文件
|
|||
|
在`res/values/config.xml`中添加配置:
|
|||
|
```xml
|
|||
|
<resources>
|
|||
|
<!-- 网络重连配置 -->
|
|||
|
<integer name="max_reconnect_attempts">5</integer>
|
|||
|
<integer name="initial_reconnect_delay_ms">2000</integer>
|
|||
|
<integer name="max_reconnect_delay_ms">30000</integer>
|
|||
|
|
|||
|
<!-- 错误重试配置 -->
|
|||
|
<integer name="max_retry_attempts">3</integer>
|
|||
|
<integer name="retry_delay_ms">5000</integer>
|
|||
|
|
|||
|
<!-- 网络监控配置 -->
|
|||
|
<bool name="enable_network_monitoring">true</bool>
|
|||
|
<integer name="network_check_interval_ms">5000</integer>
|
|||
|
</resources>
|
|||
|
```
|
|||
|
|
|||
|
### 15.2 初始化配置
|
|||
|
```java
|
|||
|
private void initNetworkConfiguration() {
|
|||
|
Resources res = getResources();
|
|||
|
|
|||
|
// 重连配置
|
|||
|
// 注意:实际实现中应通过构造函数或setter方法传递这些值
|
|||
|
// 而不是直接修改类的静态字段
|
|||
|
|
|||
|
// 错误重试配置
|
|||
|
// NetworkErrorHandler.MAX_RETRY_ATTEMPTS =
|
|||
|
// res.getInteger(R.integer.max_retry_attempts);
|
|||
|
// NetworkErrorHandler.RETRY_DELAY_MS =
|
|||
|
// res.getInteger(R.integer.retry_delay_ms);
|
|||
|
|
|||
|
// 网络监控配置
|
|||
|
boolean enableMonitoring = res.getBoolean(R.bool.enable_network_monitoring);
|
|||
|
if (enableMonitoring && networkMonitor == null) {
|
|||
|
networkMonitor = new NetworkMonitor();
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 16. 总结
|
|||
|
|
|||
|
本设计文档详细描述了阿里百炼模型网络错误处理与自动重连机制的完整解决方案。通过实现以下核心组件:
|
|||
|
|
|||
|
1. **网络状态监听器** - 实时监控网络连接状态变化
|
|||
|
2. **错误处理模块** - 分类处理不同类型的网络错误
|
|||
|
3. **重连管理器** - 实现智能的指数退避重连策略
|
|||
|
4. **状态管理系统** - 管理对话状态转换和UI更新
|
|||
|
|
|||
|
该方案具有以下优势:
|
|||
|
|
|||
|
- **自动恢复** - 网络恢复后自动重连,无需用户干预
|
|||
|
- **智能重试** - 采用指数退避算法,避免频繁重连
|
|||
|
- **用户体验** - 提供清晰的状态提示和进度显示
|
|||
|
- **资源优化** - 合理管理资源,避免内存泄漏
|
|||
|
- **可配置性** - 支持通过配置文件调整重连参数
|
|||
|
- **可扩展性** - 模块化设计便于功能扩展
|
|||
|
|
|||
|
通过实施该方案,可以显著提高阿里百炼AI对话系统在网络不稳定环境下的稳定性和用户体验。
|