NullPointerException in HandlerThread

て烟熏妆下的殇ゞ 提交于 2019-12-04 07:08:24

The only reason for me would be that queueImage() method is called before onLooperPrepared() so mHandler is not initialize.

Update

HandlerThread is simply a Thread with implementation of the run() method where onLooperPrepared() is called.

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();//It's HERE
    Looper.loop();
    mTid = -1;
}

So when it's called depends on starting this thread. If you start it and immediately call public method on the reference of this thread you may encounter a race condition and mHandler is not initialized on time.

One solution would be a delay for start processing images or playing with synchronization techniques. However, I would use much simpler way.

Just to be clear, you want your mHandler to be initialized just after HandlerThread is created and you don't want to do it explicitly from the Main Activity where HandlerThread is created.

Update 2

Just come up with the following solution.

queueImage() provides simple and light data. You could check if mHandler is null, if it's true add parameters of queueImage() to that queue. When onLoopPrepared() is called check if there is anything is that queue and process that data.

private LinkedBlockingQueue<Pair<String,Integer>> mQueue = new LinkedBlockingQueue<Pair<String,Integer>>();

public void queueImage(String url, int pos) {
    if (mHandler == null) {
        mQueue.put(new Pair<String,Integer>(url, pos));
        return;
    }
    mHandler
        .obtainMessage(MESSAGE_DOWNLOAD, pos, 0, url)
        .sendToTarget();
}

@Override
protected void onLooperPrepared() {

    // Create a message handler to handle the message queue
    mHandler = new MessageHandler(ImageDownloaderThread.this);
    //TODO check the queue here, if there is data take it and process
    //you can call queueImage() once again for each queue item
    Pair<String, Integer> pair = null;
    while((pair = mQueue.poll()) != null) {
        queueImage(pair.first, pair.second);
    }
}

I meet same question. I solved by calling wait() before before queueing message and calling call notifyAll() in onLooperPrepared. This don't need additional variables that store pending messages.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!