Android:为什么我不能在新线程中创建处理程序

ngu*_*cse 27 java multithreading android handler

我在新线程中创建处理程序时遇到问题.这是我的代码:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {
        public void run() {
            Handler handler = new Handler();
        }
    }).start();
}
Run Code Online (Sandbox Code Playgroud)

但它引起了错误!有人可以向我解释一下吗?非常感谢!

以下是我的错误的详细信息:

09-17 18:05:29.484: E/AndroidRuntime(810): FATAL EXCEPTION: Thread-75
09-17 18:05:29.484: E/AndroidRuntime(810): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-17 18:05:29.484: E/AndroidRuntime(810):  at android.os.Handler.<init>(Handler.java:197)
09-17 18:05:29.484: E/AndroidRuntime(810):  at android.os.Handler.<init>(Handler.java:111)
09-17 18:05:29.484: E/AndroidRuntime(810):  at com.example.handler.MainActivity$1.run(MainActivity.java:57)
09-17 18:05:29.484: E/AndroidRuntime(810):  at java.lang.Thread.run(Thread.java:856)
Run Code Online (Sandbox Code Playgroud)

Ale*_*ood 80

你也可以使用HandlerThread这样的:

HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
Run Code Online (Sandbox Code Playgroud)

HandlerThreads Looper与它们相关联,所以这不会引发异常.

  • 不要忘记在工作线程内停止Looper,否则它将保持线程并且不会让它死亡.完成后使用thread.quit()或thread.quitSafely(). (5认同)

nan*_*esh 21

线程lifecycle在run方法返回后立即完成.但是,由于您Handler在此创建了一个thread,因此Handler需要运行该线程才能接收消息并处理它们.

因此,为此,run方法不应该退出.因此,您需要一个Looper无限期地等待并处理到达Handler的消息.

new Thread(new Runnable() {
        public void run() {
            Looper.prepare();
            Handler handler = new Handler();
            Looper.loop();
        }
    }).start();
Run Code Online (Sandbox Code Playgroud)


Jai*_*dit 12

简答:因为您尝试连接处理程序的线程没有弯针.所以Handler类的构造函数抛出异常.您可以使用HandlerThread类,这只是Android框架提供的一个方便的类.

请阅读以下内容,了解引擎盖下发生的事情.

让我们首先尝试单独讨论所有部分.

  1. 线:

一个.线程只是一个执行流程.默认情况下,线程只是执行其runnable(如果提供)或调用其run方法.在调用新的Thread.start()时.当run方法执行run(){----}中写入的所有语句时,线程就会死掉并且Gc'd.

湾 Android中有一个Looper的概念.这基本上使线程成为阻塞线程.简单地说就是不让线程死掉.它进入阻塞状态并等待更多消息再次恢复执行.

下面是你如何设置一个阻塞线程,即一个带有looper的线程.

  new Thread(new Runnable() {
    public void run() {
        Looper.prepare();
        Looper.loop();
    }
}).start();
Run Code Online (Sandbox Code Playgroud)

这里创建了一个线程,它不仅在执行Looper.loop()语句后死掉.相反,它循环并进入阻塞状态.现在你必须要问阻塞状态是什么意思,线程将如何脱离阻塞状态?我现在如何最终发布这个帖子?这就是Handler的用武之地

  1. 处理器:

一个.它总是将自身附加到线程的Looper上,在该线程上创建其实例.

湾 然后它处理它附加的线程的那些消息.

将线程和处理程序放在一起.

new Thread(new Runnable() {
        public void run() {
            Looper.prepare();
            handler = new Handler();
            Looper.loop();
        }
    }).start();
Run Code Online (Sandbox Code Playgroud)

一个.处理程序如何附加到这个新创建的线程.湾 该线程被设置为阻塞循环线程.所以这不会死.

现在,我们可以1.在此处理程序上发送消息.2.在此处理程序上发布runnable.

它们都将在附加的线程上执行.

您可以选择扩展Handler类并实现方法handleMessage(Message msg).或者您只是在处理程序类的构造函数中提供Handler.Callback的实现.无论哪种方式,都会在附加的线程上调用handleMessage(Messages msg).

要退出线程,您可以发送特定类型的消息类型,并在收到该消息后,您只需调用Looper.myLooper().quit()

class LooperThread extends Thread {
   public Handler mHandler;

   public void run() {
      Looper.prepare();

      mHandler = new Handler() {
          public void handleMessage(Message msg) {
              // process incoming messages here
              if(msg.what == -1){
              Looper.myLooper().quit();
              }
          }
      };

      Looper.loop();
   }
}
Run Code Online (Sandbox Code Playgroud)

我希望它有助于理解整体概念.


Fun*_*onk 5

Handler需要在Looper线程中初始化,或者给它一个Looper.

根据您的要求,您可以将线程设置为Looper,如下所示:

new Thread(new Runnable() {
    public void run() {
        Looper.prepare();
        mHandler = new Handler();
        Looper.loop();
    }
}).start();
Run Code Online (Sandbox Code Playgroud)

由于Looper位于后台线程中,因此无法更新UI.您可以替代地从另一个线程向Handler提供一个Looper - 在此示例中,Handler可用于更新UI:

new Thread(new Runnable() {
    public void run() {
        Handler handler = new Handler(Looper.getMainLooper());
    }
}).start();
Run Code Online (Sandbox Code Playgroud)