How do I ensure another Thread's Handler is not null before calling it?

后端 未结 3 1348
北荒
北荒 2020-12-15 13:32

My program threw a NullPointerException the other day when it tried to use a Handler created on another thread to send that thread a message. The Handler created by the othe

相关标签:
3条回答
  • I'd go with the classic wait/notify

    public class LooperThread extends Thread {
    
        private Handler mHandler;
    
        public void run() {
            Looper.prepare();
    
            synchronized (this) {
                mHandler = new Handler() {
                    public void handleMessage(Message msg) {
                        // process incoming messages here
                    }
                };
                notifyAll();
            }
    
            Looper.loop();
        }
    
        public synchronized Handler getHandler() {
            while (mHandler == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    //Ignore and try again.
                }
            }
            return mHandler;
        }
    }
    

    Handler returned from getHandler can then be used many times without invoking synchronized getHandler.

    0 讨论(0)
  • 2020-12-15 14:04

    Preparing a Looper can block for a while, so I imagine you're hitting a condition where prepare() takes a moment to complete, thus mHandler is still undefined.

    You could have your Thread extend HandlerThread, though even then you still have to wait to ensure the Looper has initialised. Perhaps something like this might work, where you have the Handler defined separately, but utilising the Looper of your custom thread.

    Maybe.

    private void setUp() {
        mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
        mHandlerThread.start();
    
        // Create our handler; this will block until looper is initialised
        mHandler = new CustomHandler(mHandlerThread.getLooper());
        // mHandler is now ready to use
    }
    
    private class CustomThread extends HandlerThread {
        public void run() {
            // ...
        }
    }   
    
    private class CustomHandler extends Handler {
        CustomHandler(Looper looper) {
            super(looper);
        }
    
        @Override
        public void handleMessage(Message msg) {
            // ...
        }
    }
    
    0 讨论(0)
  • 2020-12-15 14:08

    I just want to add that the checked answer is the best one but if you test it like that is not going to work becouse you need to call super on run methode since it's in charge of preparing the looper so the code should be like this:

    private void setUp() {
      mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
      mHandlerThread.start();
    
      // Create our handler; this will block until looper is initialised
      mHandler = new CustomHandler(mHandlerThread.getLooper());
      // mHandler is now ready to use
    }
    
    private class CustomThread extends HandlerThread {
       public void run() {
        super.run() // <- VERY IMPORTANT OTHERWISE IT DOES NOT WORK
        // your code goes here
       }
    }   
    
    private class CustomHandler extends Handler {
    CustomHandler(Looper looper) {
        super(looper);
    }
    
     @Override
     public void handleMessage(Message msg) {
        // ...
     }
    

    }

    0 讨论(0)
提交回复
热议问题