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

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


问题原因分析

  1. 空指针触发原因:主线程调用newThread.start()后立即执行getLooper(),此时工作线程可能还未执行到Looper.prepare(),导致getLooper()返回null,后续创建Handler时传入null触发空指针。
  2. 业务逻辑缺陷:工作线程中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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:53:00