knowledgeseeker
knowledgeseeker

Reputation: 1203

Thread Runnable in kotlin runs fine in emulator but gives error on device

The following code run fine on emulator but gives following error when running on device

Only the original thread that created a view hierarchy can touch its views.

 Thread(Runnable {
  name.setText(ob.get("name").toString());
 }).start();

Upvotes: 1

Views: 795

Answers (2)

Paolo
Paolo

Reputation: 595

You cannot manipulate the UI Thread (AKA Main Thread) from a background Thread. This is how things work on most (if not all) UI frameworks. In Android the UI is handled by the UI Thread and only it can manipulate all the things related to the UI.

The fact that your code works on an emulator can be due to pure case and maybe, if you run it a dozen/hundread times it seems to work. This is the same behavior of when a multithreaded code seems to work all the times and maybe weeks or even years later stops working because of a deadlock or a race condition.

Aving said that, and given the very few context available, you can go with runOnUiThread() but pls read this before.

Just one last thing: if you are retrieveving data in a background thread from some source (database? network?) it is strange having direct access to view elements. You should relagate your background logic somewhere else (a Repository for example), and avoid using "plain" Threads especially on Activities/Fragments or other short lived components, given that Threads can outlive the Activity/Fragment lifecycle in case of a configuration change. If you do not pay very very much attention, the reference to the view inside the Thread can cause a memory leak, causing a reference to your activity to be keept in memory (after the system finished it) and thus preventing the garbage collector to eliminate it. In a few words you are at risk of an OutOfMemoryException.

Upvotes: 0

Nirav Bhavsar
Nirav Bhavsar

Reputation: 2233

Inside your thread, put your settext code in below code.

In general, you touched a UI View from another thread, so you have to executed on UI Thread in a Runnable instance passed to runOnUiThread() method.

runOnUiThread(new Runnable() {

  @Override
  public void run() {

    // write your UI name.settext code here.
    name.setText(ob.get("name").toString());

  }
});

For Kotlin

[email protected](java.lang.Runnable {
this.name.text = (ob.get("name").toString())
})

Refrerence:- for runOnUiThread

Upvotes: 1

Related Questions