【报错提示】java.lang.RuntimeException: Cant create handler inside thread

news/2025/3/15 4:03:02/文章来源:https://www.cnblogs.com/yddbkdz/p/18344036

报错提示

遇到一个报错: java.lang.RuntimeException: Can't create handler inside thread Thread[OkHttp https://a.fxltsbl.com/...] that has not called Looper.prepare()  分析

 1. 这个报错提示是在一个没有调用 Looper.prepare() 的线程中尝试创建一个 Handler 对象。

在 Android 开发中这是不允许的。在 Android 中,Handler 通常用于与 UI 线程进行通信,因此必须在 UI 线程上创建和使用它。

 2. 根据报错信息:
java.lang.RuntimeException: Can't create handler inside thread Thread[OkHttp https://a.fxltsbl.com/...] that has not called Looper.prepare()
可以看出问题出现在名为 OkHttp https://a.fxltsbl.com/... 的线程中,这是一个非 UI 线程,但尝试在这个线程上创建了 Handler。 

解决方法

解决方法通常是确保 Handler 的创建和使用发生在主线程(UI 线程)上,或者如果需要在后台线程中使用 Handler,则需要先创建一个与该线程关联的 Looper。以下两种解决方法参考: 

 1. 第一种方法

可以从报错看出:当前在子线程中尝试创建了一个 Handler 实例,而 Android 的 Handler 需要在主线程中使用,因为它依赖于主线程的消息循环(Looper)。

如果在代码中,我们使用的网络请求的回调方法是在 OkHttp 的工作线程中执行的,那么直接在这里创建 Handler 是不合适的。
 
 解决这个问题的方法是,在回调方法中确保使用主线程来执行 callback.onFailure() 和 callback.onResponse() 方法。

Android 中有几种方式可以切换到主线程,最常见的是使用 runOnUiThread() 方法或者使用 Handler 来进行线程间通信。

修改后的代码示例,使用 runOnUiThread() 来确保在主线程执行回调:

private static void setHttpRequestAgent() {//创建okhttpclient对象OkHttpClient okHttpClient = new OkHttpClient.Builder().build();//创建Request 对象Request request = new Request.Builder().url("https://api.github.com/").build();//创建call对象Call call = okHttpClient.newCall(request);//通过call.enqueue方法来提交异步请求call.enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {// 在这里处理异步请求失败的逻辑,切换到主线程执行回调runOnUiThread(() -> callback.onFailure(e.getMessage()));}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {// 在这里处理异步请求成功的逻辑,切换到主线程执行回调runOnUiThread(() -> {try {callback.onResponse(response.code(), response.body().string());} catch (IOException e) {callback.onFailure(e.getMessage());}});}});}});
}// 在 Activity 或者 Fragment 中定义一个辅助方法 runOnUiThread,用于确保在主线程执行任务
private void runOnUiThread(Runnable action) {new Handler(Looper.getMainLooper()).post(action);
}

 


在上面的代码中,使用了 runOnUiThread() 方法来确保在主线程上执行 callback.onFailure() 和 callback.onResponse()。这样可以避免在子线程中直接操作 UI 导致的问题。


2. 第二种方法

如果希望在子线程中使用 Handler,需要先调用 Looper.prepare() 初始化一个 Looper,并且在使用完毕后调用 Looper.loop() 来启动消息循环。

这样可以确保在子线程中正确使用 Handler 来进行消息处理,包括处理网络请求的回调。 

修改后的示例代码,以在子线程中使用 Handler 处理网络请求的回调:

private static void setHttpRequestAgent() {OkHttpClient client = new OkHttpClient.Builder().build();MTSDK.getInstance().setHttpRequestAgent(new HttpRequestAgent() {@Overridepublic void request(String protocol, String url, String params, HttpRequestCallback callback) {new Thread(() -> {// 初始化 Looper
                Looper.prepare();Handler handler = new Handler(Looper.myLooper()) {@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);switch (msg.what) {case MSG_FAILURE:callback.onFailure((String) msg.obj);break;case MSG_RESPONSE:ResponseData responseData = (ResponseData) msg.obj;callback.onResponse(responseData.code, responseData.body);break;}}};RequestBody body = RequestBody.create(params, MediaType.parse("application/json; charset=utf-8"));Request request = new Request.Builder().url(url).post(body).build();// 使用之前创建的 OkHttpClient 实例 client 进行网络请求client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {// 处理请求失败的逻辑,通过 Handler 发送消息到主线程处理回调Message message = handler.obtainMessage(MSG_FAILURE, e.getMessage());message.sendToTarget();}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {// 处理请求成功的逻辑,通过 Handler 发送消息到主线程处理回调String responseBody = response.body().string();ResponseData responseData = new ResponseData(response.code(), responseBody);Message message = handler.obtainMessage(MSG_RESPONSE, responseData);message.sendToTarget();}});// 启动消息循环
                Looper.loop();}).start();}});
}// 定义一个简单的数据类用于存储响应信息
private static class ResponseData {int code;String body;ResponseData(int code, String body) {this.code = code;this.body = body;}
}// 定义消息类型
private static final int MSG_FAILURE = 1;
private static final int MSG_RESPONSE = 2;

 

上面的代码中,在 request 方法中创建了一个新的线程,并在该线程中初始化了一个 Looper 和 Handler。

在网络请求的回调方法中,通过 Handler 发送消息到主线程处理回调,确保了在子线程中正确使用了 Looper 和 Handler 来进行线程间通信。

这种方法适合于需要在子线程中处理网络请求的情况,并且需要将结果传递回主线程更新 UI。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/778330.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷-P9830 题解

思路分析 分析样例:见红线,长宽各为 2,存在格点;黄线长 2 宽 3,没有格点。 考虑延长黄线使得长 4 宽 6,发现有格点。思考格点,如果长和宽都可以被分成 \(p\times l\) 的格式,则存在格点。那么,就能想出: 推论 1:对于 \((0 \ , \ 0)\) 和 \((x \ , \ y)\) 之间没有格…

kubernetes-存储卷与持久化详解

目录背景volume介绍emptyDirHostPathNFSconfigMapSecretPersistentVolume介绍PV回收策略PV访问策略基于nfs或nas创建pv创建hostpath类型的pvPV的状态PersistentVolumeClaim创建pvc与pv进行绑定使用pvc动态存储storageclass创建目录nfs添加授权目录创建yaml 背景 容器部署过程中…

如何通过视频剪辑软件修复原始视频声音小的问题 All In One

如何通过视频剪辑软件修复原始视频声音小的问题 All In One 视频后期处理 (剪映)如何通过视频剪辑软件修复原始视频声音小的问题 All In One视频后期处理 (剪映)demos视频声音太小了, 音量开到 100%,还是听不清,建议加个麦,或者后期处理视频的时候提高音量https://www.bilib…

kettle从入门到精通 第八十四课 ETL之kettle kettle中Get data from XML使用实战教程

场景:解析xml文件或者内容解析出其中某些字段。 本来想着这个步骤使用起来比较简单,就没有梳理成文,结果群里的小伙伴为了使用这个步骤折腾了一下午。故有了此文。 在开始学习之前我们一起来学习下xml命名空间的相关知识,为下文展开做基础铺垫。 1、xml命名空间XML 的命名空…

双边滤波

双边滤波(Bilateral Filtering)是一种非线性的图像处理方法,主要用于图像的平滑同时保持边缘清晰。与传统的低通滤波器(如均值滤波或高斯滤波)不同,双边滤波不仅考虑了空间上的邻近性,还考虑了像素值的相似性,这使得它能够在去除噪声的同时较好地保留图像的边界和细节。…

用项目详细讲讲vue3路由

1.【对路由的理解】 Vue Router 是 Vue.js 官方的路由管理器,它用于构建单页面应用(SPA),允许我们在不同的页面间进行导航,而无需刷新整个页面。 路由配置文件代码如下:import {createRouter,createWebHistory} from vue-router import Home from @/pages/Home.vue impo…

多态的概念,前提,注意事项以及访问成员的特点 day09

多态:某一个事物在不同状态下的多种状态举例:1、学生是人,老师是人,医生是人。2、汽态的水是水,固态的水是水,液态的水是水在java中要实现多态的话,需要有3个前提:1、必须要有继承关系2、要有方法的重写(思考可否不重写?)不是必须要重写的,重写可以体现子类的专属特…

[vue3] vue3初始化渲染流程

本文解析了 Vue3 组件初次渲染的流程,涵盖应用程序初始化、核心渲染步骤,以及 vnode 的创建和渲染,探讨了 Vue3 内部机制及其跨平台实现的关键细节。组件初次渲染流程 组件是对DOM树的抽象,组件的外观由template定义,模板在编译阶段会被转化为一个渲染函数,用于在运行时生…

[米联客-安路飞龙DR1-FPSOC] SDK入门篇连载-03 GPIO PS/PL实验

软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台:https://milianke.tmall.com/ 登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑! 1 概述本…

2024/8/5笔记

字符串专题 1 暑假二南集训 day1 A - GT考试 洛谷 - P3193 [HNOI2008] GT考试 题目描述 阿申准备报名参加 GT 考试,准考证号为 \(N\) 位数\(X_1,X_2…X_n\ (0\le X_i\le 9)\),他不希望准考证号上出现不吉利的数字。 他的不吉利数字\(A_1,A_2,\cdots, A_m\ (0\le A_i\le 9)\) …

[米联客-安路飞龙DR1-FPSOC] SDK入门篇连载-02 FPSoc程序固化入门

软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台:https://milianke.tmall.com/ 登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑! 1概述在…

[米联客-安路飞龙DR1-FPSOC] SDK入门篇连载-01 FPSoc开发入门

软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台:https://milianke.tmall.com/ 登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑! 1概述1.…