user947659
user947659

Reputation: 2645

While Loop inside Thread not working?

I have a very simple UI and i need to constantly run a check process, so I am trying to use a Thread with a while loop. When I run the loop with nothing but a Thread.sleep(1000) command, it works fine, but as soon as I put in a display.setText(), the program runs for a second on the emulator then quits. I cannot even see the error message since it exits so fast.

I then took the display.setText() command outside the thread and just put it directly inside onCreate, and it works fine (so there is no problem with the actual command).

here is my code, and help will be greatly appreciated. Thank you!

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);



    on=(Button) findViewById(R.id.bon);
    off=(Button) findViewById(R.id.boff);
    display=(TextView) findViewById(R.id.tvdisplay);
    display2=(TextView) findViewById(R.id.tvdisplay2);
    display3=(TextView) findViewById(R.id.tvdisplay3);
    stopper=(Button) findViewById(R.id.stops);


    stopper.setOnClickListener(new View.OnClickListener() {


        @Override

        public void onClick(View v) {
            // TODO Auto-generated method stub
            if(boo=true)
            {
                boo=false;
                display3.setText("System Off");
            }
            else{
                boo=true;
            }
            }
    });





    Thread x = new Thread() {
        public void run() {
            while (boo) {
                 display3.setText("System On");

                try {
                    // do something here
                    //display3.setText("System On");

                    Log.d(TAG, "local Thread sleeping");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Log.e(TAG, "local Thread error", e);
                }

            }
        }
    };


    display3.setText("System On");
    display3.setText("System On");


    x.start();
}

Upvotes: 0

Views: 6730

Answers (5)

Byhieg
Byhieg

Reputation: 1

In non-UI thread,you can't update UI.In new Thread,you can use some methods to notice to update UI.

  1. use Handler
  2. use AsyncTask
  3. use LocalBroadcast
  4. if the process is the observer pattern,can use RxJava

Upvotes: -1

Kurtis Nusbaum
Kurtis Nusbaum

Reputation: 30845

You should encapsulate this code in an AsyncTask instead. Like so:

private class MyTask extends AsyncTask<Void, Void, Void> {
  private Activity activity;
  MyTask(Activity activity){
    this.activity = activity;
  }  

  protected Long doInBackground() {
    while (true){
      activity.runOnUiThread(new Runnable(){
        public void run(){
          display3.setText("System On");
        }
      });
      try{
        Thread.sleep(1000);
      }catch (InterruptedException e) {
        Log.e(TAG, "local Thread error", e);
      }
   }  
}

Then just launch the task from your onCreate method.

Upvotes: 0

Jong
Jong

Reputation: 9125

When you are not in your UI thread, instead of display3.setText("test") use:

display3.post(new Runnable() {
    public void run() {
        display3.setText("test");
    {
});

Upvotes: 0

Ted Hopp
Ted Hopp

Reputation: 234857

You can't update the UI from a non-UI thread. Use a Handler. Something like this could work:

// inside onCreate:
final Handler handler = new Handler();
final Runnable updater = new Runnable() {
    public void run() {
        display3.setText("System On");
    }
};

Thread x = new Thread() {
    public void run() {
        while (boo) {
            handler.invokeLater(updater);

            try {
                // do something here
                //display3.setText("System On");

                Log.d(TAG, "local Thread sleeping");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Log.e(TAG, "local Thread error", e);
            }

        }
    }
};

You could also avoid a Handler for this simple case and just use

        while (boo) {
            runOnUiThread(updater);
            // ...

Alternatively, you could use an AsyncTask instead of your own Thread class and override the onProgressUpdate method.

Upvotes: 3

Aaron Gage
Aaron Gage

Reputation: 2403

Not 100% certain, but I think it is a case of not being able to modify UI controls from a thread that did not create them?

Upvotes: 0

Related Questions