Android中使用getLooper()方法报错,请求技术协助
Android线程中断场景下getLooper()调用空指针问题解决
我正在学习Android线程与并发编程,编写了一个基础程序:让主线程在5秒后向工作线程发送中断信号以停止其处理。程序包含主线程和工作线程,但调用getLooper()时触发空指针异常。
原代码如下:
package com.example.testthread; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create a new thread and start it NewThread newThread = new NewThread(); newThread.start(); // Get the Looper of the new thread and create a Handler associated with it Looper looper = newThread.getLooper(); mHandler = new Handler(looper); // Post a Runnable to the new thread's Handler after a delay of 5 seconds mHandler.postDelayed(new Runnable() { @Override public void run() { newThread.interrupt(); } }, 5000); } private static class NewThread extends Thread { private boolean isRunning = true; @Override public void run() { Looper.prepare(); while (isRunning) { Log.d("NewThread", "Thread is running"); try { Thread.sleep(1000); } catch (InterruptedException e) { Log.d("NewThread", "Thread was interrupted"); isRunning = false; } } Looper.loop(); } } }
报错信息:Attempt to read from field 'android.os.Looper android.os.Thread.mLooper' on a null object reference
问题原因分析
- 空指针触发原因:主线程调用
newThread.start()后立即执行getLooper(),此时工作线程可能还未执行到Looper.prepare(),导致getLooper()返回null,后续创建Handler时传入null触发空指针。 - 业务逻辑缺陷:工作线程中
Looper.loop()要等到while循环结束才会调用,此时消息队列完全未启动,postDelayed的任务永远不会被执行,无法触发线程中断。
修复方案
方案一:移除不必要的Looper,直接用主线程Handler实现延迟中断
原需求仅需主线程延迟触发中断,完全不需要工作线程的Looper和Handler,简化代码即可解决问题:
package com.example.testthread; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.util.Log; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NewThread newThread = new NewThread(); newThread.start(); // 利用主线程Handler延迟5秒发送中断 new Handler().postDelayed(() -> { newThread.interrupt(); }, 5000); } private static class NewThread extends Thread { private boolean isRunning = true; @Override public void run() { while (isRunning) { Log.d("NewThread", "Thread is running"); try { Thread.sleep(1000); } catch (InterruptedException e) { Log.d("NewThread", "Thread was interrupted"); isRunning = false; // 可选:重置线程中断状态,避免后续逻辑受影响 Thread.currentThread().interrupted(); } } } } }
方案二:保留工作线程Looper(适用于需消息处理场景)
如果后续需要工作线程处理消息,需修正Looper启动逻辑,并确保正确获取Looper:
package com.example.testthread; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; public class MainActivity extends AppCompatActivity { private Handler mWorkerHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NewThread newThread = new NewThread(); newThread.start(); // 等待工作线程初始化Looper new Thread(() -> { while (newThread.getLooper() == null) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } // 初始化工作线程Handler mWorkerHandler = new Handler(newThread.getLooper()); // 延迟发送中断指令 mWorkerHandler.postDelayed(() -> { newThread.interrupt(); }, 5000); }).start(); } private static class NewThread extends Thread { private boolean isRunning = true; @Override public void run() { Looper.prepare(); // 将业务逻辑post到消息队列,确保Looper.loop()启动后能执行 new Handler().post(() -> { while (isRunning) { Log.d("NewThread", "Thread is running"); try { Thread.sleep(1000); } catch (InterruptedException e) { Log.d("NewThread", "Thread was interrupted"); isRunning = false; // 退出Looper,避免线程阻塞 Looper.myLooper().quit(); } } }); // 启动消息循环 Looper.loop(); } } }
内容的提问来源于stack exchange,提问作者Ninad Walanj
相关产品推荐
相关产品推荐

