4

I'm new to android.I'm building app to listen incoming message over WiFi , it works fine for listening and updating UI but when i try to exit it doesn't respond to back button press until it receive message in buffer. From my understanding, buttons are on UI thread and Runnable is a separate thread and that's why it doesn't respond to button press immediately coz its busy on separate thread. So how can i interrupt "Runnable" from back button press?

Any help would be much appreciated.

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 : Sorry, I should have post this earlier , so in "onCreate" , i use handler to call "mUpdate" . Is it the right way to call or not?

    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

    }
Raj23
  • 57
  • 2
  • 2
  • 5

2 Answers2

2

Edit:

Now that you've added code that involves the Handler it's now clearer where your trouble lies. Some points to understand:

  • Android has a general concept that there is the main thread and then there are many other threads.
  • Only the main thread may modify the UI
  • In later versions of android the main thread is not allowed to do networking...

So how to change the UI based on reading something from the network?

You need to pass a message from another (networking) thread to the main thread. The Handler let's your other thread give a message to the main thread... That is your networking thread can give a task (Runnable) to the main thread to perform. The handler posts the task from the networking thread to the main thread.

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) {}
    }
}; 

May I suggest you also:

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

Original Answer (Now defunct)

From my understanding, buttons are on UI thread and Runnable is a separate thread and that's why it doesn't respond to button press immediately coz its busy on separate thread.

That's not correct at all. A Thread is a separate thread not a Runnable. And you need to call start() not run() on the thread to make the run method execute in its own thread. The whole point of using threads is that one thread will not (usually) be blocked by another being busy.

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

You can also look into an AsyncTask from the android library. This will also run in its own thread if you use it correctly.

Philip Couling
  • 13,581
  • 5
  • 53
  • 85
  • `interrupt()` merely sets the interrupt flag. It is the responsibility of the executed code to check this flag and terminate properly. – Tadas S Apr 24 '13 at 11:32
  • @afk5min yes and no. Although in this case more yes than no. It does have other effects depending on the current state of the thread. I've modified the answer to fix this. http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29 – Philip Couling Apr 24 '13 at 11:41
  • If the thread is in a blocking wait, then an InterruptedException is generated - but that exception is checked; executed code is forced to handle that situation. (Plus, the example above does not use a blocking wait) – Tadas S Apr 24 '13 at 11:45
  • agreed... thus "more yes than no" :-) – Philip Couling Apr 24 '13 at 11:49
  • Thanks for your time , i haven't try your answer yet , i'll try and then i'll mark your answer. @couling – Raj23 Apr 24 '13 at 12:27
  • @couling - it doesn't allow me to mark answer , need minimum 15 points for that. – Raj23 Apr 25 '13 at 09:49
  • @user2314699 not a problem. glad to be of service. – Philip Couling Apr 29 '13 at 16:15
  • Can you complete the code please? – Si8 Dec 04 '16 at 17:11
-1

I have no idea how that relates to Android, but judging from your title, stopping a thread in Java is done with interrupts, which are handled by the OS itself.

From you Thread you interrupt the other one.

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

And on the other side:

 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;
         }
     }
 }
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Only the `Thread#stop()` method uses JVM/native methods to kill an executing thread. `interrupt()` merely sets the thread interrupt flag and does not do anything else. – Tadas S Apr 24 '13 at 11:35
  • @afk5min ups. I forgot to add the while(true) loop. See my edit. Will that make you happy? Also how do you think an interrupt is done internally if not some native apis (POSIX threads, Solaris threads, Windows threads, etc)? Setting a flag *might* be true, but it depends on the implementation and there is nothing in the javadoc about that. ;) – Eugene Apr 24 '13 at 12:03
  • @couling this is fun! No, really, read the documentation of interrupt from an Android project and from an non-Android project. They differ. That is why I started with " I have no idea if this relates to Android". :) P.S. I also forgot about the break statement there after an interrupt was caught, I did not even compile this - just a hint that in PLAIN JAVA it should be done with interrupt. – Eugene Apr 24 '13 at 16:00
  • @couling InputStream, Socket.. what? I am aswering the question based only on the title, I thought that was obvious. I will no longer engage in this useless discussion. – Eugene Apr 24 '13 at 16:34
  • @couling I just opened up eclipse and coded this. It makes perfect sense - Thread.sleep was missing. This is so obvious that I did not even think of it. Cheers – Eugene Apr 24 '13 at 16:55