Андроид: почему я не могу создать обработчик в новом потоке

у меня была проблема, что я не могу создать обработчик в новом потоке. Вот мой код:

    @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.run(MainActivity.java:57)
09-17 18:05:29.484: E/AndroidRuntime(810):  at java.lang.Thread.run(Thread.java:856)

4 ответов


вы также можете использовать HandlerThread такой:

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

HandlerThreadС Looper связанные с ними, так что это не исключение.


нити!--1--> завершается сразу после возвращения метода run. Но так как вы создаете Handler в этой thread, обработчику нужно, чтобы поток был запущен для получения сообщений и их обработки.

поэтому для этого метод run не должен выходить. Следовательно, вам нужен петлитель, чтобы ждать бесконечно и обрабатывать сообщения, которые поступают в обработчик.

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

короткий ответ: Потому что поток, на который вы пытаетесь прикрепить обработчик, не имеет петлителя. И поэтому конструктор класса Handler бросает исключение. Вместо этого вы могли бы использовать класс HandlerThread, это просто удобный класс, предоставляемый платформой Android.

пожалуйста, читайте ниже, что происходит под капотом.

давайте сначала попробуем обсудить все детали по отдельности.

  1. автор:

a. Нить просто поток исполнения. Предполагается, что поток по умолчанию просто выполняет свой runnable (если он предоставлен) или вызывает свой метод run. При вызове нового потока.начать.)( Поток просто умирает и Gc'D, когда метод run выполняет все инструкции, написанные внутри run () { - - - -}.

b. Существует концепция Looper в Android. Что в основном делает поток блокирующим потоком. Проще говоря, это просто не дает нити умереть. Он переходит в состояние блокировки и ждет новых сообщений возобновите его выполнение.

ниже показано, как вы настроили блокирующий поток i.e нить с петлителем.

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

здесь создается поток, который не просто умирает после выполнения цикла.оператор цикла. Вместо этого он делает петлю и переходит в блокирующее состояние. Теперь вы должны спросить, что означает состояние блокировки, как поток выйдет из состояния блокировки ? как мне, наконец, выпустить эту нить ? здесь приходит обработчик в

  1. обработчик:

a. Он всегда присоединяется к петле потока, на котором создается его экземпляр.

b. Затем он обрабатывает сообщения потока, к которому присоединяется.

соединяя резьбу и обработчики.

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

a. Как обработчик присоединяется к этому вновь созданному потоку. b. Поток настроен как блокирующий поток looper. Так что этого не будет. умереть.

Теперь мы можем 1. Отправить сообщение на этот обработчик. 2. Сообщение runnable на этом обработчике.

оба они будут выполняться в прикрепленном потоке.

у вас есть возможность либо расширить класс обработчика и реализовать метод handleMessage(Message msg). или вы просто предоставляете реализацию обработчика.Обратный вызов в конструкторе класса handler. В любом случае handleMessage(сообщения msg) будет вызываться в прикрепленном потоке.

чтобы выйти из потока, вы можете отправить определенный тип сообщения, и после получения этого сообщения Вы просто вызовете Looper.myLooper().quit ()

класс LooperThread расширяет поток { общественный обработчик 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();
  }

}

Я надеюсь, что это помогло понять общую концепцию.


обработчик должен быть инициализирован в потоке Looper или иметь заданный ему Looper.

в зависимости от того, что вы хотите сделать, вы можете настроить свой поток так:

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

С лупера идет в фоновом потоке, вы не можете обновить UI. Вы можете поочередно дать обработчику цикл из другого потока - в этом примере обработчик можно использовать для обновления пользовательского интерфейса:

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