簡體   English   中英

Android:為什么我不能在新線程中創建處理程序

[英]Android: Why can't I create a handler in new thread

我在新線程中創建處理程序時遇到問題。 這是我的代碼:

    @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();
}

但它引起了錯誤! 有人可以向我解釋一下嗎? 非常感謝!

以下是我的錯誤的詳細信息:

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)

你也可以像這樣使用HandlerThread

HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
Handler handler = new Handler(thread.getLooper());

HandlerThread有一個與它們相關聯的Looper ,所以這不會引發異常。

Thread的lifecycle在run方法返回后立即完成。 但是由於您在此thread中創建了一個Handler ,因此Handler需要運行該線程才能接收消息並處理它們。

因此,為此,run方法不應該退出。 因此,您需要一個Looper無限期地等待並處理到達Handler的消息。

new Thread(new Runnable() {
        public void run() {
            Looper.prepare();
            Handler handler = new Handler();
            Looper.loop();
        }
    }).start();

簡答:因為您嘗試連接處理程序的線程沒有彎針。 所以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();

這里創建了一個線程,它不僅在執行Looper.loop()語句后死掉。 相反,它循環並進入阻塞狀態。 現在你必須要問阻塞狀態是什么意思,線程將如何脫離阻塞狀態? 我現在如何最終發布這個帖子? 這就是Handler的用武之地

  1. 處理器:

一個。 它總是將自身附加到線程的Looper上,在該線程上創建其實例。

然后它處理它附加的線程的那些消息。

將線程和處理程序放在一起。

new Thread(new Runnable() {
        public void run() {
            Looper.prepare();
            handler = new Handler();
            Looper.loop();
        }
    }).start();

一個。 處理程序如何附加到這個新創建的線程。 該線程被設置為阻塞循環線程。 所以這不會死。

現在,我們可以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();
   }
}

我希望它有助於理解整體概念。

Handler需要在Looper線程中初始化,或者給它一個Looper。

根據您的要求,您可以將線程設置為Looper,如下所示:

new Thread(new Runnable() {
    public void run() {
        Looper.prepare();
        mHandler = new Handler();
        Looper.loop();
    }
}).start();

由於Looper位於后台線程中,因此無法更新UI。 您可以替代地從另一個線程向Handler提供一個Looper - 在此示例中,Handler可用於更新UI:

new Thread(new Runnable() {
    public void run() {
        Handler handler = new Handler(Looper.getMainLooper());
    }
}).start();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM