11
localChatManager.addIncomingListener { from, message, chat ->

                Log.v(TAG,"listener")


                //You can't modify views from non-UI thread.
                this@chatActivity.runOnUiThread { object :Runnable{
                    override fun run() {
                        Log.i(TAG,"runOnUiThread")
                     }
                } }
            }

I am not able to figure out why runOnUiThread is not working but outside of that method everything is working as usual.

Ankur Khandelwal
  • 1,042
  • 3
  • 19
  • 40

5 Answers5

29

What you are doing is passing in a lambda to the runOnUiThread function. It will run that lambda, and create an object that inherits from Runnable, and then do nothing with it. Maybe you can see that a little bit better if you format it like this (added some extra log statements and explanation):

runOnUiThread({
    Log.i(TAG, "This is run")
    object : Runnable {                    // This whole expression
        override fun run() {               // returns an object which
            Log.i(TAG, "runOnUiThread")    // is a Runnable, but does
        }                                  // not at any point invoke
    }                                      // its "run" method
    Log.i(TAG, "And so is this")
})

The created object is not assigned to a variable, and is never used. If you want to pass in a Runnable instance to the runOnUiThread method, you can do that by just putting it inside the parentheses of the runOnUiThread call:

runOnUiThread(
        object : Runnable {
            override fun run() {
                Log.i(TAG, "runOnUiThread")
            }
        }
)

The simplest way to use runOnUiThread though is to pass in a lambda to it using SAM conversion, and writing the code you want to execute directly inside that.

runOnUiThread { 
    Log.i(TAG, "runOnUiThread") 
}

Here's the official documentation covering SAM conversions, which happens to use Runnable in its examples.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
2

The above answer is correct and should be accepted.
In case your are coming from Java, here is an example of the equivalent Java of your code:

    runOnUiThread(new Runnable() { // This runnable is created
        @Override                  // from lambda by SAM convention
        public void run() {

            new Runnable() {       // This Runnable is instantiated
                @Override          // inside the lambda but never runs.
                public void run() {
                    Log.i(TAG, "runOnUiThread");
                }
            };
        }
    });

I hope you can see how the inner code doesn't get executed.

RobCo
  • 6,240
  • 2
  • 19
  • 26
0

Rx based Answer:

import rx.Observable

Observable.just(true)
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe{
              // your code
           }
OhhhThatVarun
  • 3,981
  • 2
  • 26
  • 49
hamid keyhani
  • 451
  • 3
  • 12
0

Its better to work with coroutines

Try using

runBlocking (Dispatchers.Main) {
   // any Main thread needs
}
Jerin
  • 688
  • 1
  • 9
  • 21
0
// This is running on a coroutine thread
fun doSomeBackgroundWork() {
  // Perform some work in the background
  val result = performLongRunningOperation()

  // Get a reference to the main thread's Looper
  val mainLooper = Looper.getMainLooper()

  // Create a Handler to run some code on the UI thread
  val handler = Handler(mainLooper)
  handler.post {
    updateUi(result)
  }
}
Tyler2P
  • 2,324
  • 26
  • 22
  • 31