4

For example, if I have a thread doing expensive stuff, and from that thread I want to fire runOnUiThread in the Main (activity) class. Obviously I shouldn't make an instance of my activity class (Main). So if I try

 Main.runOnUiThread(mRunnable);

from my thread it gives me an error saying it's not a static method, and therefor it can't be accessed in my way. Now my understanding would be that the activity class is nearly almost accessed in a static way.
How would I do this?

(Btw: I'm doing this because I was getting CalledFromWrongThreadException, Only the original thread that created a view hierarchy can touch it's views)

usealbarazer
  • 707
  • 3
  • 10
  • 27

6 Answers6

4

Raunak has the right idea. I'll just add that you can also specify an integer in the method sendEmptyMessage as an identifier to the handler. This will allow you to create one handler that can handle all of your UI updates, e.g.

public static final int EXAMPLE = 0;
public static final int ANOTHER_EXAMPLE = 1;

private final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        switch( msg.what ){
            case EXAMPLE: 
                //Perform action
                break;
            case ANOTHER_EXAMPLE;
                //Perform action
                break;
        }
    }
} 

//Call to submit handler requesting the first action be called
handler.sendEmptyMessage(EXAMPLE);

Hope this helps!

Ljdawson
  • 12,091
  • 11
  • 45
  • 60
3

You should use the Handler class. The handler class runs on the UI thread. When you finish work in your thread, call handler.sendEmptyMessage(), from where you can make the changes to your ui.

private final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
         // make changes to ui
    }
} 
Raunak
  • 6,427
  • 9
  • 40
  • 52
  • 4
    This answer is misleading. From `Handler`'s documentation: *When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.* In other words, **it only runs on the UI thread if the object was created there.** – blubb Jun 10 '13 at 09:23
  • See http://stackoverflow.com/a/25250494/199364 for how to fix this so it is always on UI thread. – ToolmakerSteve Jun 23 '15 at 00:20
3

Your question doesn't really provide enough details, but from the sound of things, you're in a private inner class (Runnable?) in your activity (Main). If that is the case, you can either write:

Main.this.runOnUiThread(mRunnable);

or

runOnUiThread(mRunnable); //will see that there is no runOnUiThread in the current class and begin looking "upwards"

Also, you may want to look at AsyncTask, specifically at the onPostExecute, onPreExecute and onProgressUpdate callbacks, which run on the UI thread.

Jon Willis
  • 6,993
  • 4
  • 43
  • 51
2

first create a runnable outside onCreate. Like this:

private Runnable myRunnable = new Runnable() {
        @Override
        public void run() {

                        //work to be done

        }
    };

and then call the runnable using:

runOnUiThread(myRunnable);
Nigel Crasto
  • 318
  • 3
  • 8
0

For those who are looking for an easy instant solution follow the simple steps

  • Make a reference of your class before your onCreate() method

    MyClass obj;
    
  • Initialize it in you onCreate() method

    obj = MyClass.this;
    
  • Call runOnUiThread()

    obj.runOnUiThread(new Runnable() {
        public void run() {
        //perform your UI tasks here
        }
    });
    

Hope it helps.

Sagar
  • 3,107
  • 2
  • 26
  • 35
Syeda Zunaira
  • 5,191
  • 3
  • 38
  • 70
0

all of the above answers are not very correct.

1)if you want a piece of code to run on UI thread from any thread code base. you can do: Looper.getMainLooper().post(new Runnable(...))

because Looper.getMainLooper() is a static variable and initialized in ActivityThread.

2) if your runnable code snippet is inside an activity then you can use:

MainActivity.this.runOnUiThread(...)