You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Service的Thread中使用OkHttp请求报错的排查与解决

问题分析与修复方案

嘿,我来帮你搞定这个错误!你遇到的Can't create handler inside thread that has not called Looper.prepare()异常,其实是Android线程机制的典型问题,我来给你一步步拆解:

错误日志

E/AndroidRuntime: FATAL EXCEPTION: Thread-468 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

错误根源

  1. 多余的线程创建:IntentService的onHandleIntent方法本身就运行在系统为它分配的独立后台线程中,你没必要再手动创建新的Thread。这种冗余的线程不仅会增加管理成本,还容易引发上下文生命周期的问题。
  2. Looper缺失:你手动创建的子Thread默认没有初始化Looper,而如果在这些线程中执行了需要依赖Handler的操作(比如Toast提示、UI更新,或者某些内部使用Handler的组件),就会抛出这个异常——因为Handler必须依附于一个带有Looper的线程才能工作。

修复方案

方案1:移除手动创建的Thread(推荐)

直接在onHandleIntent的后台线程中执行网络请求,完全符合IntentService的设计初衷:

修改你代码中的循环部分:

// 原错误代码
for (int i = 1; i <= soluongtp; i++) {
    final int k = i;
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                jsonDataAPIS.add(jsonToObject(GET("https://api.apixu.com/v1/forecast.json?key=c848c4ffa3ef4e5787494645181403&q=" + URLEncoder.encode("nametp" + String.valueOf(k), "UTF-8") + "&days=7")));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            Log.d("Log", "thuc hien thread");
        }
    });
    thread.start();
}

替换为:

// 修改后的代码
for (int i = 1; i <= soluongtp; i++) {
    try {
        jsonDataAPIS.add(jsonToObject(GET("https://api.apixu.com/v1/forecast.json?key=c848c4ffa3ef4e5787494645181403&q=" + URLEncoder.encode("nametp" + String.valueOf(i), "UTF-8") + "&days=7")));
        Log.d("Log", "thuc hien task " + i);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

方案2:如果必须保留子Thread(不推荐)

如果你有特殊需求必须手动创建Thread,那么需要在Thread的run方法中初始化Looper:

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // 初始化Looper
        Looper.prepare();
        try {
            jsonDataAPIS.add(jsonToObject(GET("https://api.apixu.com/v1/forecast.json?key=c848c4ffa3ef4e5787494645181403&q=" + URLEncoder.encode("nametp" + String.valueOf(k), "UTF-8") + "&days=7")));
            // 如果需要显示Toast,现在可以正常执行了
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Log.d("Log", "thuc hien thread");
        // 结束Looper循环(避免线程阻塞)
        Looper.myLooper().quit();
    }
});
thread.start();

额外的优化建议

  • UI操作必须切换到主线程:你的代码里定义了private TextView textView;,绝对不能在后台线程直接更新它,需要通过Broadcast或者绑定主线程Looper的Handler来发送更新请求:
    // 在IntentService中初始化绑定主线程的Handler
    private Handler uiHandler = new Handler(Looper.getMainLooper());
    
    // 在后台线程中调用UI操作
    uiHandler.post(new Runnable() {
        @Override
        public void run() {
            textView.setText("更新内容");
            Toast.makeText(getApplicationContext(), "Vui lòng bật GPS...", Toast.LENGTH_SHORT).show();
        }
    });
    
  • 移除StrictMode的全局放行:你代码里的StrictMode.setThreadPolicy(policy)会绕过Android的线程安全检查,虽然能临时解决问题,但会隐藏潜在的线程风险,建议按照规范处理线程操作后移除这段代码。

内容的提问来源于stack exchange,提问作者Ngọc Anh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:35:48