
本文详解如何在 android java 项目中为“无移动数据与 wi-fi”场景添加专属 dialog 错误提示,涵盖状态码识别、网络检测逻辑、ui 响应联动及最佳实践。
本文详解如何在 android java 项目中为“无移动数据与 wi-fi”场景添加专属 dialog 错误提示,涵盖状态码识别、网络检测逻辑、ui 响应联动及最佳实践。
在 Android 开发中,准确识别并友好提示网络异常(尤其是完全无网络连接)是提升用户体验的关键环节。本教程以一个典型遗留项目为例,指导你如何基于已有错误码体系(如 NO_NETWORK_ERROR = 3),科学地补充网络连通性校验逻辑,并安全触发自定义 Dialog 提示,避免仅依赖服务端返回的状态码——因为当设备彻底离线时,HTTP 请求根本无法发出,onFailure() 才是真正的捕获入口。
✅ 正确做法:在 onFailure() 中识别真实断网状态
原答案中直接使用 ConnectivityManager.TYPE_MOBILE == 0 是错误且无效的(TYPE_MOBILE 是常量值,非运行时状态)。正确方式是通过 ConnectivityManager 获取当前活动网络,并判断其是否为空或不可用:
// 在 Activity 或 Fragment 中(需 Context)
private boolean isNetworkAvailable() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
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 {
// 兼容旧版本(API < 23)
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnected();
}
}⚠️ 注意:getActiveNetworkInfo() 自 Android 10(API 29)起已弃用,必须针对 API 23+ 使用 NetworkCapabilities,否则在新系统上将始终返回 false。
? 修改 ApiCallBack.onFailure() —— 主动注入网络状态判断
关键修改点:在 onFailure() 中,当捕获到 UnknownHostException 或 SocketTimeoutException 等典型离线异常时,立即调用本地网络检测,若确认无网络,则主动抛出 NO_NETWORK_ERROR:
立即学习“Java免费学习笔记(深入)”;
@Override
public void onFailure(Call<ApiResponse<T>> call, Throwable t) {
if (t instanceof UnknownHostException ||
t instanceof SocketTimeoutException ||
t instanceof IOException && !t.getMessage().contains("Failed to connect")) {
// 主动检测设备真实网络状态
if (!isNetworkAvailableInContext()) { // 需传入 Context 或 Application 实例
onError(new ApiErrorCodeInfo(StatusCodeUtil.NO_NETWORK_ERROR,
"No internet connection available"));
return;
}
}
// 其他异常按原有逻辑处理
if (t instanceof UnknownHostException) {
onError(new ApiErrorCodeInfo(StatusCodeUtil.URL_INVALID, t.getLocalizedMessage()));
} else {
onError(new ApiErrorCodeInfo(StatusCodeUtil.INTERNAL_SERVER_ERROR,
t.getLocalizedMessage()));
}
}
// 辅助方法:需确保 application 可访问(已在构造函数中持有)
private boolean isNetworkAvailableInContext() {
ConnectivityManager cm = (ConnectivityManager) application.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NetworkCapabilities cap = cm.getNetworkCapabilities(cm.getActiveNetwork());
return cap != null &&
(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
(cap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
cap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)));
} else {
NetworkInfo info = cm.getActiveNetworkInfo();
return info != null && info.isConnected();
}
}? UI 层响应:统一处理 NO_NETWORK_ERROR
回到 Activity 的观察者逻辑,保持简洁清晰,仅依据状态码分支,不重复做网络检测(避免冗余和竞态):
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) {
// ✅ 此处触发专用网络错误 Dialog
showNetworkErrorDialog(); // 推荐封装为独立方法
} else {
loginErrorDialog(loginStatusInfo.getMessage());
}
});? 封装 showNetworkErrorDialog() —— 专业级提示体验
private void showNetworkErrorDialog() {
new AlertDialog.Builder(this)
.setTitle(getString(R.string.network_error_title))
.setMessage(getString(R.string.network_require_msg))
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
// 可选:跳转系统网络设置页
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
startActivity(intent);
})
.setNegativeButton(R.string.cancel, null)
.setCancelable(false)
.show();
}✅ 总结与最佳实践
- 不要依赖服务端返回 NO_NETWORK_ERROR:离线时请求发不出,该码只应在客户端主动检测后注入。
-
务必适配 Android 新旧网络 API:NetworkCapabilities(≥API 23)与 NetworkInfo(
- 权限声明不可少:在 AndroidManifest.xml 中添加:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 如需跳转设置页,无需额外权限 -->
- 避免内存泄漏:AlertDialog 持有 Activity 引用,确保在 onDestroy() 中 dismiss 或使用 WeakReference 管理。
- 测试覆盖场景:飞行模式、关闭 Wi-Fi/移动数据、弱网超时,验证各路径均能准确触发对应 Dialog。
- 权限声明不可少:在 AndroidManifest.xml 中添加:
通过以上结构化实现,你将获得一个鲁棒、可维护、符合 Android 最佳实践的无网络错误提示方案——既复用现有架构,又填补关键体验缺口。










