2013-04-24 3 views
4

Я новичок в android.Imm приложение для создания приложения для прослушивания входящего сообщения через WiFi, он отлично работает для прослушивания и обновления пользовательского интерфейса, но когда я пытаюсь выйти из него, он не отвечает на нажмите кнопку до тех пор, пока не получите сообщение в буфере. С моей точки зрения, кнопки находятся в потоке пользовательского интерфейса, а Runnable - это отдельный поток, и поэтому он не отвечает на нажатие кнопки сразу же, когда он занят отдельной ветвью. Итак, как я могу прерывать нажатие кнопки «Runnable»?Как остановить или выйти из режима «Runnable»

Любая помощь будет высоко оценена.

public Runnable mUpdate = new Runnable() { 
    public void run() {    
     try { 
      line = in.readLine(); 
      newtext.setText(line); 
      mHandler.post(this); 
      Log.i("RESPONSE FROM SERVER", "S: Received Message: '" +line+ "'"); 

      //onBackPressed(); 
      //threadRunning = true; 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.e("Error" , "Something Happen");  
     } 
    } 
}; 

Edit: К сожалению, я должен был пост об этом раньше, так и в "OnCreate", я использую обработчик для вызова "mUpdate". Правильно ли это позвонить или нет?

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    intent = getIntent(); 
    setContentView(R.layout.activity_display_message); 
    message = intent.getStringArrayExtra(MainActivity.EXTRA_MESSAGE); 
    newtext = (TextView)findViewById(R.id.TextView1); 
    userName = message[0]; 
    serverIP = message[1]; 
    sendConnectionRequest(); 
    mHandler = new Handler(); // Handler to update UI  
    mHandler.post(mUpdate);  // post is a method to update UI 

    } 

ответ

2

Edit:

Теперь, когда вы добавили код, который включает в Handler это теперь ясно, где ваша беда. Некоторые моменты, чтобы понять:

  • Android имеет общую концепцию, что есть основной поток, а затем есть много других потоков.
  • только основной поток может изменять интерфейс
  • В более поздних версиях андроида основной поток не разрешается делать сети ...

Так как изменить пользовательский интерфейс на основе читать что-то из сети ?

Вам необходимо передать сообщение с другой (сетевой) темы в основной поток. Обработчик позволяет вашему другому потоку передать сообщение в основной поток ... Это ваш сетевой поток может дать задачу (Runnable) в основной поток для выполнения. Обработчик отправляет задачу из сетевого потока в основной поток.

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    intent = getIntent(); 
    setContentView(R.layout.activity_display_message); 
    message = intent.getStringArrayExtra(MainActivity.EXTRA_MESSAGE); 
    newtext = (TextView)findViewById(R.id.TextView1); 
    userName = message[0]; 
    serverIP = message[1]; 
    sendConnectionRequest(); 
    mHandler = new Handler(); // Handler to update UI 
           // This is being created in the main thread 
           // so everything posted will be posted to 
           // the main thread 

    mUpdate.start();   // start thread to do something on the network 
           //before updating the UI 

} 

public Thread mUpdate = new Thread() { 
    public void run() {    
     try { 
      while (!thread.interrupted()) { 
       final String line = in.readLine(); 
       Log.i("RESPONSE FROM SERVER", "S: Received Message: '" +line+ "'"); 

       // Define the UI change you want to make 
       Runnable uiUpdate = new Runnable() { 
        public void run() { 
         // modify your UI here. 
         newtext.setText(line); 
        } 
       }; 

       // post the UI change back to the main thread. 
       mHandler.post(uiUpdate); 
      } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.e("Error" , "Something Happen");  
     } 
    } 

    public void interrupt() { 
     try { 
      super.interrupt(); 
      in.close(); 
     } 
     catch (IOException e) {} 
    } 
}; 

Могу ли я предложить вам также:

protected void onDestroy() { 
    mUpdate.interrupt(); 
} 

оригинальный ответ (ныне несуществующей)

Из моего понимания, кнопки находятся на UI потоке и Runnable представляет собой отдельный поток и поэтому он не реагирует на нажатие кнопки сразу же, когда он занят отдельной ветвью.

Это совсем не так. A Thread - отдельная нить не Runnable. И вам нужно позвонить start(), а не run(), чтобы поток выполнялся в своем потоке. Весь смысл использования потоков состоит в том, что один поток не будет (обычно) заблокирован другим занятым.

// <snip>removed for brevity of new answer</snip> 

Вы также можете посмотреть в AsyncTask из андроида библиотеки. Это также будет работать в своем потоке, если вы будете использовать его правильно.

+0

'прерывания()' просто устанавливает флаг прерывания. Ответственный за выполненный код должен проверить этот флаг и закончить его надлежащим образом. – afk5min

+0

@ afk5min да и нет. Хотя в этом случае больше да, чем нет. Он имеет другие эффекты в зависимости от текущего состояния потока. Я изменил ответ, чтобы исправить это. http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29 –

+0

Если поток находится в ожидании блокировки, генерируется InterruptedException, но это исключение проверено; исполняемый код вынужден обрабатывать эту ситуацию. (Кроме того, приведенный выше пример не использует ожидающий блокировки) – afk5min

-1

Я понятия не имею, как это относится к Android, но, судя по вашему названию, остановка потока в Java выполняется с прерываниями, которые обрабатываются самой ОС.

От вас Thread вы прерываете другой.

theOtherThread.interrupt() //--> inside your Thread. 

А с другой стороны:

public void run(){ 
    while(true){ 
      try{ 
       //handle your logic 
       Thread.sleep(100); 
      }catch(InterruptedException){ 
      //thread was 'stopped' here 
      Thread.currentThread().interrupt(); //this is a MUST 
      break; 
     } 
    } 
} 
+0

Только метод 'Thread # stop()' использует JVM/native методы для уничтожения исполняемого потока. 'interrupt()' просто устанавливает флаг прерывания потока и ничего не делает. – afk5min

+0

@ afk5min ups. Я забыл добавить цикл while (true). См. Мое редактирование. Это сделает вас счастливыми? Также, как вы думаете, что прерывание выполняется внутри, если не какой-либо родной apis (потоки POSIX, потоки Solaris, потоки Windows и т. Д.)? Установка флага * может * быть правдой, но это зависит от реализации, и в javadoc ничего нет. ;) – Eugene

+0

@couling это весело! Нет, действительно, прочитайте документацию о прерывании от проекта Android и от проекта, отличного от Android. Они различаются. Вот почему я начал с «Я понятия не имею, относится ли это к Android». :) P.S. Я также забыл про инструкцию break после того, как было поймано прерывание, я даже не скомпилировал это - просто намек на то, что в PLAIN JAVA это должно быть сделано с прерыванием. – Eugene

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