头图

在这里插入图片描述

摘要

本文以鸿蒙App开发中常见的HTTP请求失败问题为切入点,通过实现一个城市天气查询功能的完整案例,详细讲解网络请求的常见故障点及解决方案。我们将从权限配置到代码实现,再到错误排查,带你一步步打通鸿蒙网络请求的任督二脉。

问题描述与场景分析

在鸿蒙应用开发中,当我们需要从服务器获取数据时(如天气信息、新闻列表等),HTTP请求失败是最常见的痛点之一。最近我在开发天气查询应用时就遇到了这个问题:点击查询按钮后,界面卡住无响应,控制台也没有明确错误信息。这种情况通常由以下原因导致:

  • 网络权限未配置
  • URL或API密钥错误
  • 跨域请求被拦截
  • 主线程阻塞
  • 服务器响应格式异常

解决方案:天气查询功能实现

权限配置(config.json)

{
  "app": {
    "bundleName": "com.example.weather",
    "vendor": "example",
    "version": "1.0.0"
  },
  "module": {
    "reqPermissions": [{
      "name": "INTERNET",
      "reason": "获取天气数据需要网络访问权限"
    }]
  }
}

关键点:没有网络权限,任何请求都会直接失败且无错误提示!鸿蒙权限申请必须显式声明。

完整天气查询代码(Java)

// WeatherSlice.java
public class WeatherSlice extends AbilitySlice {
    private TextField cityInput;
    private Text weatherResult;
    private static final String API_KEY = "YOUR_API_KEY"; // 替换实际key
    private static final String BASE_URL = "https://api.openweathermap.org/data/2.5/weather";

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        // 界面布局代码略...
        
        Button queryButton = (Button) findComponentById(ResourceTable.Id_query_btn);
        queryButton.setClickedListener(v -> {
            String city = cityInput.getText();
            if (!city.isEmpty()) {
                // 在后台线程执行网络请求
                TaskDispatcher dispatcher = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
                dispatcher.asyncDispatch(() -> fetchWeather(city));
            }
        });
    }

    private void fetchWeather(String city) {
        String url = BASE_URL + "?q=" + city + "&appid=" + API_KEY + "&units=metric";
        HttpURLConnection connection = null;
        
        try {
            URL requestUrl = new URL(url);
            connection = (HttpURLConnection) requestUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            
            if (connection.getResponseCode() == 200) {
                InputStream input = connection.getInputStream();
                String result = StreamUtils.readStream(input);
                
                // 解析JSON数据
                JSONObject json = new JSONObject(result);
                JSONObject main = json.getJSONObject("main");
                String weather = "温度:" + main.getDouble("temp") + "℃\n" +
                                  "湿度:" + main.getInt("humidity") + "%";
                
                // 更新UI必须切回主线程
                getUITaskDispatcher().asyncDispatch(() -> 
                    weatherResult.setText(weather));
            } else {
                showError("服务器返回错误:" + connection.getResponseCode());
            }
        } catch (Exception e) {
            showError("请求失败:" + e.getMessage());
        } finally {
            if (connection != null) connection.disconnect();
        }
    }

    private void showError(String msg) {
        getUITaskDispatcher().asyncDispatch(() -> 
            weatherResult.setText(msg));
    }
}

代码关键点解析

权限声明:在config.json中声明INTERNET权限是网络请求的前提
异步请求:使用TaskDispatcher将网络请求放入后台线程,避免阻塞UI
超时设置setConnectTimeout(5000)防止无响应请求永久挂起
线程切换:通过getUITaskDispatcher().asyncDispatch()安全更新UI
错误处理:捕获所有异常并展示友好错误信息
资源释放:在finally块中确保关闭HttpURLConnection

API密钥注意:示例中使用OpenWeatherMap API,需到官网注册获取真实密钥(免费)

常见问题排查手册

权限配置错误

现象:请求无响应,日志无错误信息
验证方法:检查config.json是否包含INTERNET权限

主线程阻塞

现象:界面卡顿,ANR警告
解决方案:确保网络请求在后台线程执行

URL构造错误

现象:服务器返回404
调试技巧

// 打印完整URL验证
HiLog.debug(LABEL, "Request URL: %{public}s", url);

跨域问题(CORS)

现象:浏览器调试正常,App请求失败
解决方案:服务器需设置响应头:

Access-Control-Allow-Origin: *

HTTPS证书问题

现象:SSLHandshakeException异常
临时方案(仅限调试):

// 创建信任所有证书的Client
TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {
        public void checkClientTrusted(...) {}
        public void checkServerTrusted(...) {}
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
    }
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

测试结果展示

当正确实现后,应用运行效果如下:

输入:北京
输出:
温度:23.5℃
湿度:65%

错误场景模拟:

输入:不存在的城市名
输出:服务器返回错误:404

断开网络后请求:
输出:请求失败:Unable to resolve host...

性能分析

时间复杂度:O(1)

  • 单次HTTP请求时间取决于网络延迟
  • JSON解析复杂度与固定数据结构相关

空间复杂度:O(1)

  • 内存占用恒定(不随输入数据规模增长)
  • 流处理避免大文件内存溢出

总结与经验

在鸿蒙应用中进行网络请求时,务必记住三个黄金法则:
权限优先:没有声明INTERNET权限,一切归零
线程分离:主线程只处理UI,网络操作放后台
错误兜底:所有网络操作必须try-catch

通过本文的天气查询案例,我们完整走过了HTTP请求从实现到调试的全流程。实际开发中,推荐使用鸿蒙的@ohos.net.http模块进行更简洁的请求处理,但底层原理与本文演示一致。当遇到"神秘消失"的请求时,按照网络权限->URL验证->线程检查->错误捕获的顺序排查,99%的问题都能快速定位。

最终建议:生产环境务必使用HTTPS,并在服务器配置正确的CORS策略,这才是网络请求畅通无阻的终极保障。

前端视界
5.1k 声望1.2k 粉丝