Android继承HandlerThread开发时handleMessage方法不执行问题求助
问题根因
- 未启动HandlerThread:仅实例化ThumbnailDownloader、添加生命周期观察者,没有调用
start()方法启动线程,导致HandlerThread的Looper不会初始化,onLooperPrepared()回调完全不会执行,你定义了handleMessage逻辑的requestHandler从未被正确赋值。 - queueThumbnail方法错误覆盖Handler实例:每次调用queueThumbnail时都重新执行
requestHandler = Handler(),无参构造的Handler默认绑定主线程Looper,且没有重写handleMessage处理逻辑,所有下载消息都被发送到这个无逻辑的主线程Handler,自然不会触发下载流程。 - 无参Handler构造方法已废弃:Android API 30开始
Handler()无参构造方法被标记废弃,该方法默认绑定当前线程Looper,隐式持有上下文容易引发内存泄漏,要求必须显式传入Looper实例。
修改方案
不需要额外调整Looper底层配置,只需修改以下几处错误即可:
- 启动HandlerThread,保证Looper初始化回调正常触发
- 删除queueThumbnail里覆盖Handler的错误代码
- 初始化Handler时显式传入后台线程的Looper,修复废弃告警
- 生命周期销毁时主动停止线程,避免内存泄漏
代码修改示例
PhotoGalleryFragment修改部分
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) retainInstance = true photoGalleryViewModel = ViewModelProvider(this).get(PhotoGalleryViewModel::class.java) thumbnailDownloader = ThumbnailDownloader() lifecycle.addObserver(thumbnailDownloader) // 新增:启动HandlerThread线程 thumbnailDownloader.start() }
ThumbnailDownloader修改部分
fun queueThumbnail (target: T, url: String) { Log.i (TAG, "Got a url: $url") requestMap[target] = url // 删除错误的requestHandler = Handler()代码,直接用onLooperPrepared初始化的实例发消息 requestHandler.obtainMessage(MESSAGE_DOWNLOAD, target).sendToTarget() } @Suppress("UNCHECKED_CAST") override fun onLooperPrepared() { // 显式传入当前HandlerThread的looper,修复废弃告警,绑定后台线程Looper requestHandler = object : Handler(looper) { override fun handleMessage(msg: Message) { if (msg.what == MESSAGE_DOWNLOAD) { val target = msg.obj as T Log.i (TAG, "Got a request for URL: ${requestMap[target]}") handleRequest(target) } } } } @OnLifecycleEvent (Lifecycle.Event.ON_DESTROY) fun tearDown() { Log.i (TAG, "Destroying background thread") // 新增:停止线程Looper,避免内存泄漏 quit() }
修改完成后重新运行即可看到预期日志,handleMessage逻辑会正常在后台线程执行。
内容的提问来源于stack exchange,提问作者Dmitry Kurowsky
相关产品推荐
相关产品推荐

