2015-11-22 2 views
1

Я искал связь между потоком и петлером, и я просто знаю, что означает буквальный смысл двух слов. Когда приходят в конкретные условия, я все еще немного смущен.Должен ли я вызвать Looper.prepare() в потоке?

Я столкнулся с этой проблемой при попытке создать приложение для связи с устройством Bluetooth. У меня проблемы с подключением.

private class ConnectThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final BluetoothDevice mmDevice; 
    private String mSocketType; 

    public ConnectThread(BluetoothDevice device, boolean secure) { 
     mmDevice = device; 
     BluetoothSocket tmp = null; 
     mSocketType = secure ? "Secure" : "Insecure"; 

     // Get a BluetoothSocket for a connection with the 
     // given BluetoothDevice 
     try { 
      if (secure) { 
       tmp = device.createRfcommSocketToServiceRecord(
         MY_UUID_SECURE); 
      } else { 
       tmp = device.createInsecureRfcommSocketToServiceRecord(
         MY_UUID_INSECURE); 
      } 
     } catch (IOException e) { 
      tip("Socket Type: " + mSocketType + "create() failed"); 
     } 
     mmSocket = tmp; 
    } 

    public void run() { 
     Looper.prepare(); 
     setName("ConnectThread" + mSocketType); 

     // Always cancel discovery because it will slow down a connection 
     if(mBluetoothAdapter.isDiscovering()) 
      mBluetoothAdapter.cancelDiscovery(); 

     // Make a connection to the BluetoothSocket 
     try { 
      // This is a blocking call and will only return on a 
      // successful connection or an exception 
      mmSocket.connect(); 
     } catch (IOException e) { 
      // Close the socket 
      try { 
       mmSocket.close(); 
      } catch (IOException e2) { 
       e2.printStackTrace(); 
      } 
      connectionFailed(); 
      return; 
     } 

     // Reset the ConnectThread because we're done 
     synchronized (BluetoothThreads.this) { 
      mConnectThread = null; 
     } 

     // Start the connected thread 
     connected(mmSocket, mmDevice, mSocketType); 
     Looper.loop(); 
    } 

    public void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { 

     } 
    } 
} 

этот код загружен с образца разработчика Android. и Looper.prepare(), Looper.loop() добавляются мной. Если вы вызовете эти два метода, приложение выйдет из строя. И я получил предупреждение от студии Android: Не могу создать обработчик внутри потока, который не вызвал Looper.prepare(). Вот почему я добавляю два метода.

Я хочу спросить, правильно ли я называю эти два метода?

Почему я должен назвать их, пока я не использовал Toast или Handler, как это делают другие?

+0

Не могли бы вы указать ссылку, откуда вы взяли этот код. –

+0

[BluetoothChat] (http://developer.android.com/intl/zh-cn/samples/BluetoothChat/index.html) это ссылка, откуда я загрузил образец кода. И я должен упомянуть, что я успешно выполнил образец на своем телефоне. Но когда я пытаюсь самостоятельно построить новый проект, подобный образцу, у меня возникают проблемы с ConnectThread. – Wtswkz

+0

Убедитесь, что ваш файл build.gradle (доступный внутри папки приложения) похож на файл buid.gradle образца (доступный внутри папки приложения). Выполняя сравнение, сосредоточьтесь на версиях sdk, упомянутых в файле gradle. –

ответ

0

Я хочу спросить, правильно ли я называю два метода?

Да

Почему я должен называть их, пока я не использовал Тост или Handler, как это делают другие?

Looper.loop() и Looper().prepare() используются для создания MessageQueue и справиться с этим MessageQueue андроид рекомендует использовать Handler, так что если вы используете Looper.loop() и Looper.prepare(), то вы должны использовать Handler также.

+0

Спасибо, что ответили на мой вопрос. Я ценю это. – Wtswkz

+0

Я загружаю свой проект новой сборки в git, вот ссылка [My Project] (https://github.com/wtswzyw/YFCup2), если вы не потрудились посмотреть. На самом деле я все еще запутался, почему образец кода может работать без сбоев, и мой собственный подобный проект не может. На самом деле я не хочу обрабатывать сообщение из ConnectThread, и все, что я хочу, чтобы ConnectThread выполнял, - это подключить устройство Bluetooth и вернуть мне сокет. – Wtswkz

+0

Сделайте файл app/build.gradle похожим на файл приложения/build.gradle образца. –

0

Ну, наконец, я выясню, что случилось с моим собственным проектом. Не имеет ничего общего с build.gradle, но спасибо Android Dev все равно.

На самом деле это я сам виноват. В примере проекта BluetoothChat методы, такие как Log.d(), вызывают для указания информации об отладке. Но я не знал, где найти результат Log.d(), поэтому я заменил их Toast. Я думал, что все будет хорошо. Но я считаю, что Toast не могут быть использованы в ConnectThread, в противном случае он будет бросать исключение:

java.lang.RuntimeException: Невозможно создать обработчик внутри потока, который не называется Looper.prepare()

И я использовал Toast в методе connectionFailed(), вот в чем проблема.

+0

Но нет тоста в коде, который вы упомянули выше. Тост создаст проблему внутри рабочего потока, так как ему нужен поток пользовательского интерфейса. –

0

На самом деле, вы делаете неLooper.prepare() и Looper.loop(). Это необходимо только в том случае, если вы хотите присоединить к потоку Handler, что в вашем случае я не вижу такого требования.

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

Примечание: Для отладки всегда используйте Log.d()/Log.w()/Log.e() и избегать использования тостов.

+0

Да, я понимаю, что сейчас – Wtswkz

Смежные вопросы