Transfer to the new Handler in the child thread and report an error--Can't create handler inside thread that has not called Looper.prepare()

Why does a new Handler report the following error in a child thread?

java.lang.RuntimeException: 

Can't create handler inside thread that has not called Looper.prepare() 

This is because the Handler object and its caller are in the same thread. If a delay operation is set in the Handler, the calling thread will also be blocked. Each Handler object is bound to a Looper object, and each Looper object corresponds to a message queue (MessageQueue). If the Looper object bound to it is not specified when the Handler is created, the system will bind the Looper of the current thread to the Handler by default.
In the main thread, you can directly use new Handler() to create a Handler object, which will be automatically bound to the Looper object of the main thread; creating a Handler directly in a non-main thread will result in an error, because the Android system is not the main thread by default Looper is not turned on in , and the Handler object must be bound to the Looper object. In this case, there are two ways to solve this problem:

Method 1: You need to manually open the Looper in the thread (Looper.prepare()-->Looper.loop()), and then bind it to the Handler object;

final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //Execute time-consuming operation
    try {

      Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());

      Thread.sleep(2000);
      Log.e("bm", "The time-consuming operation is finished~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    Looper.prepare();
    new Handler().post(runnable);//Go directly to a new handler in the child thread
    Looper.loop(); //In this case, the Runnable object is run in the child thread In the thread, network operations can be performed, but the UI cannot be updated
  }
}.start();

 

Method 2: Get the Looper of the main thread through Looper.getMainLooper() and bind it to this Handler object.

final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //Execute time-consuming operation
    try {

      Log.e("bm", "runnable thread: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
      Thread.sleep(2000);
      Log.e ("bm", "The time-consuming operation is completed~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    new Handler(Looper.getMainLooper ()).post(runnable) ;//Go directly to a new handler in the child thread

    //In this case, the Runnable object is running in the main thread and cannot be networked, but the UI can be updated
  }
}.start();

 

I thought I was just a programmer, but I'm actually a programmer...

Why does a new Handler report the following error in a child thread?

java.lang.RuntimeException: 

Can't create handler inside thread that has not called Looper.prepare() 

This is because the Handler object and its caller are in the same thread. If a delay operation is set in the Handler, the calling thread will also be blocked. Each Handler object is bound to a Looper object, and each Looper object corresponds to a message queue (MessageQueue). If the Looper object bound to it is not specified when the Handler is created, the system will bind the Looper of the current thread to the Handler by default.
In the main thread, you can directly use new Handler() to create a Handler object, which will be automatically bound to the Looper object of the main thread; creating a Handler directly in a non-main thread will result in an error, because the Android system is not the main thread by default Looper is not turned on in , and the Handler object must be bound to the Looper object. In this case, there are two ways to solve this problem:

Method 1: You need to manually open the Looper in the thread (Looper.prepare()-->Looper.loop()), and then bind it to the Handler object;

final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //Execute time-consuming operation
    try {

      Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());

      Thread.sleep(2000);
      Log.e("bm", "The time-consuming operation is finished~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    Looper.prepare();
    new Handler().post(runnable);//Go directly to a new handler in the child thread
    Looper.loop(); //In this case, the Runnable object is run in the child thread In the thread, network operations can be performed, but the UI cannot be updated
  }
}.start();

 

Method 2: Get the Looper of the main thread through Looper.getMainLooper() and bind it to this Handler object.

final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //Execute time-consuming operation
    try {

      Log.e("bm", "runnable thread: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
      Thread.sleep(2000);
      Log.e ("bm", "The time-consuming operation is completed~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    new Handler(Looper.getMainLooper ()).post(runnable) ;//Go directly to a new handler in the child thread

    //In this case, the Runnable object is running in the main thread and cannot be networked, but the UI can be updated
  }
}.start();

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324776097&siteId=291194637