0

I'm new to Android development and I would like to know what is the best practice to update the UI from another class.

Example: When I enter an activity I start a function myClass.PerformCalculation() which takes some time, when the calculation is over I want to update the UI with the result of the calculation. This generates the following error:

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

I was thinking about using a Broadcast Receiver in the activity and perform a SendBroadcast at the end of myClass.PerformCalculation(), is it a good practice?

Matei Radu
  • 2,038
  • 3
  • 28
  • 45
Charles
  • 167
  • 1
  • 13
  • you should return the calculation result to the activity and update the UI in the activity. Don't use broadcasts – Tim Sep 19 '18 at 11:54
  • Thank you for the feedbacks. Based on the documentation ASyncTask seems to be the correct method to use in my case. – Charles Sep 19 '18 at 13:36

2 Answers2

3

Here the documentation to AsyncTask.

It will help you to do some background tasks, and publish the result when finished to the main UI.

From the documentation:

AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

Example of code: from Stack Answer

inner class someTask() : AsyncTask<Void, Void, String>() {
    override fun doInBackground(vararg params: Void?): String? {
        // ...
    }

    override fun onPreExecute() {
        super.onPreExecute()
        // ...
    }

    override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        // UPDATE UI HERE
    }
}
Maurice
  • 2,129
  • 2
  • 25
  • 33
0

Using RxJava:

object MyClass {
    fun performCalculation(): Single<Int> {
        return Single.fromCallable {
            //perform calculation
            1
        }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
    }
}

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        MyClass.performCalculation().subscribe { result ->
            //update ui
        }
    }
}

Using Coroutines:

object MyClass {
    fun performCalculation(): Deferred<Int> {
        return async(CommonPool) {
            //your calculation
            1
        }
    }
}

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        launch(UI) {
            val result = MyClass.performCalculation().await()
            //update ui
        }
    }
}