Search code examples
androidnullpointerexceptionhandlerlooper

NullPointerException with Looper


please help me with this. I created a progress bar and update its progress programmatically every 100ms as soon as the application starts(Yeah, it sounds odd, but just for messing-around purposes only). But everytime I run it, I keep getting a NullPointerException. Can someone please help me with this? The log indicates the NullPointerException occurred at "custom_handler.sendMessage(message);" down below. Thank you so much.

private Handler custom_handler, main_handler;
private int progress = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //TextView to display the
    text_view = (TextView)findViewById(R.id.text_view); progress

    progress_bar = (ProgressBar)findViewById(R.id.progress_bar);

    //Instantiate a new worker thread
    //but somehow its handler is not instantiated
    //by the time the compiler reaches the "custom_handler.sendMessage(message);"
    //at all, keep getting NullPointerException
    //please look at the comment below the next code block.
    new MyThread().start();

    main_handler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message message) {
            progress_bar.setProgress(message.arg1);
            text_view.setText(message.arg1 + "%");
        }
    };



        Message message = Message.obtain();
        message.obj = "Battery fully charged";

        //keep getting the exception here
        custom_handler.sendMessage(message);


}

class MyThread extends Thread {
    public void run() {
        Looper.prepare();

        custom_handler = new Handler(Looper.myLooper()) {
            public void handleMessage(Message message) {
                Toast.makeText(MainActivity.this, message.obj.toString(), Toast.LENGTH_SHORT).show();
            }
        };
        while (progress < 100) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                System.out.println("PSSSHH");
            }
            progress++;

            Message message = Message.obtain();
            message.arg1 = progress;

            main_handler.sendMessage(message);
        }
        Looper.loop();
    }
}

Solution

  • The method Thread#start() is asynchronous and non-blocking. It means that your custom_handler is going to be instantiated (inside your MyThread) but creating a new Thread is slower than running a couple of straightforward instructions. At the time the runtime is processing

    custom_handler.sendMessage(message);
    

    the custom_handler has not instantiated yet. You can confirm it by setting a breakpoint right before that line, wait a few of seconds and them resume the execution. It won't crash.

    To actually fix it you should instantiate the custom_handler before calling it, and preferably in the thread that owns it.