
本文详解如何在android旧项目中基于statuscodeutil和apicallback机制,为“无移动数据与wi-fi”场景(no_network_error=3)添加自定义网络错误对话框,并修正逻辑缺陷、增强健壮性。
本文详解如何在android旧项目中基于statuscodeutil和apicallback机制,为“无移动数据与wi-fi”场景(no_network_error=3)添加自定义网络错误对话框,并修正逻辑缺陷、增强健壮性。
在Android Java项目中,为网络异常提供友好提示是提升用户体验的关键环节。当前项目已定义 StatusCodeUtil.NO_NETWORK_ERROR = 3,但仅靠状态码触发弹窗存在明显隐患——状态码本身无法反映实时网络连通性。原答案中误将 ConnectivityManager.TYPE_MOBILE == 0 作为判断依据,这属于典型逻辑错误(TYPE_MOBILE 是常量值,恒为0,无法用于运行时检测),必须予以纠正。
✅ 正确实现步骤
1. 补充网络状态检测工具方法
在 ApiCallBack 或工具类(如 NetworkUtil.java)中添加可靠的网络检查逻辑:
public class NetworkUtil {
public static boolean isNetworkAvailable(Context context) {
if (context == null) return false;
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm != null) {
// Android 10+ 推荐使用 getNetworkCapabilities()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
return capabilities != null &&
(capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR));
} else {
// 兼容旧版本
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnected();
}
}
return false;
}
}⚠️ 注意:需在 AndroidManifest.xml 中声明权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
2. 在 ViewModel 中主动触发网络检测(推荐)
避免在 UI 层重复判断,将网络状态检查前置到业务逻辑层。例如,在登录失败回调中:
立即学习“Java免费学习笔记(深入)”;
// 在 loginViewModel 的 onError 处理逻辑中(非 Activity 观察者内)
if (apiErrorCodeInfo.getCode() == StatusCodeUtil.NO_NETWORK_ERROR) {
// 主动检查真实网络状态,防止状态码误报
if (!NetworkUtil.isNetworkAvailable(getApplication().getApplicationContext())) {
// 发布真实无网络事件
loginStatusInfo.postValue(new LoginStatusInfo(StatusCodeUtil.NO_NETWORK_ERROR, "No network available"));
} else {
// 状态码与实际不符,按其他错误处理
loginStatusInfo.postValue(new LoginStatusInfo(StatusCodeUtil.INTERNAL_SERVER_ERROR, "Unexpected error"));
}
}3. 在 Activity/Fragment 中正确响应状态码
更新观察者逻辑,仅依据 loginStatusInfo.getStatus() 判断,不插入硬编码网络检测(避免重复、耦合、错误):
loginViewModel.loginStatusInfo.observe(this, loginStatusInfo -> {
hideLoadingDialog();
int status = loginStatusInfo.getStatus();
if (status == API_SUCCESS_STATUS) {
startHomeActivity();
} else if (status == StatusCodeUtil.INTERNAL_SERVER_ERROR) {
loginErrorDialog(getString(R.string.fail_to_login_server_error));
} else if (status == StatusCodeUtil.NO_NETWORK_ERROR) {
// ✅ 安全:此状态由 ViewModel 经真实检测后发出
networkErrorDialog(getString(R.string.network_require_msg));
} else {
loginErrorDialog(loginStatusInfo.getMessage());
}
});4. 实现 networkErrorDialog() 方法(示例)
确保该方法支持跨生命周期安全调用(如使用 DialogFragment):
private void networkErrorDialog(String message) {
new AlertDialog.Builder(this)
.setTitle("Network Unavailable")
.setMessage(message)
.setPositiveButton("Settings", (dialog, which) -> {
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
startActivity(intent);
})
.setNegativeButton("Cancel", null)
.show();
}? 关键注意事项
- ❌ 禁止在 UI 层直接调用 ConnectivityManager.TYPE_MOBILE == 0:这是编译时常量,永远为真,会导致误判。
- ✅ 状态码应代表语义,而非实时状态:NO_NETWORK_ERROR 是服务端/网关返回的抽象错误类型,其真实触发条件必须由客户端主动验证后决定。
- ? 兼容性优先:getActiveNetworkInfo() 已在 Android 10+ 被弃用,务必使用 NetworkCapabilities + Build.VERSION.SDK_INT 分支处理。
- ?️ 空安全与上下文生命周期:NetworkUtil.isNetworkAvailable() 必须校验 Context 非空;AlertDialog 应在 isFinishing() / isDestroyed() 前调用,避免崩溃。
通过以上结构化实现,你不仅完成了“无网络弹窗”的功能需求,更建立了可维护、可测试、符合 Android 最佳实践的错误处理体系。










