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

You need to observe UI calls on the main thread using AndroidSchedulers.mainThread().

override fun OnUserNumberClicked(photo: UserPicture) { subscriptions.add( mRepository.userPicture() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe { userListener.updateUserNumber() } ) }

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

In the previous sections, you learned about the ins and outs of the Coroutine API. In this one, you’ll apply that knowledge to an Android project. Also, you’ll see how coroutines provide an easy solution for some of the common problems in the Android world.

The Importance of the Android Main Thread

Android developers discovered concurrency’s importance quite early. Android is inherently asynchronous and event-driven, with strict requirements for which threads certain things can run on. When a user launches an app, Android creates a process along with an execution thread - the main thread, sometimes referred to as the UI thread.

The main thread handles drawing, reacting to user events, receiving events from other apps and basically everything that happens onscreen. To keep everything running smoothly, it’s important not to overload the UI thread with additional work. If the UI thread is busy doing other work, it can’t do its job of drawing views on the screen. This might cause jerky animations, block the screen or even cause the infamous Application Not Responding (ANR) error. The only way to create a responsive app is by leaving the UI thread as free as possible by having background threads do all the hard work asynchronously.

Getting Started

In this chapter, you’ll learn what mechanisms exist for asynchronous programming on the Android platform and why coroutines perform much better. You’ll see what Kotlin coroutines bring to the table and how they simplify various facets of Android development. To see this in action, you’ll use a simple Disney Explorer app. The app fetches Disney characters from the API and lists them.

Only the original thread that created a view hierarchy can touch its views Coroutine
Ermpo pdkeor
Only the original thread that created a view hierarchy can touch its views Coroutine

Doing Heavy Work on UI Thread

Now, you’ll see what happens when the main thread is busy doing heavy work and can’t do its primary job of rendering the UI. Open BackgroundProcessingActivity.kt and find the processingMethod property. Make sure its value is set to MAIN_THREAD, like this:

private var processingMethod: ProcessingMethod = MAIN_THREAD private fun runUiBlockingProcessing() { // This will block the thread while executing showToast("Result: ${fibonacci(40)}") } private fun fibonacci(number: Int): Long { return if (number == 1 || number == 2) { 1 } else { fibonacci(number - 1) + fibonacci(number - 2) } }
Only the original thread that created a view hierarchy can touch its views Coroutine

Thread

A thread is an independent path of execution in a program. The Java Virtual Machine allows an application to have multiple threads of execution running concurrently. There are two ways to create a new thread of execution.

// Creation class MyThread : Thread() { override fun run() { doSomeWork() } } // Usage val thread = MyThread() thread.start() // Creation class MyRunnable : Runnable { override fun run() { doSomeWork() } } // Usage val runnable = MyRunnable() val thread = Thread(runnable) thread.start() private var processingMethod: ProcessingMethod = THREAD private fun runProcessingWithThread() { // Create a new Thread which will do the work Thread(getCharactersRunnable).start() } private val getCharactersRunnable by lazy { GetCharactersRunnable() } inner class GetCharactersRunnable : Runnable { override fun run() { val characters = disneyApiService.getDisneyCharacters() runOnUiThread { showResults(characters) } } }
Only the original thread that created a view hierarchy can touch its views Coroutine
com.raywenderlich.android.disneyexplorer E/AndroidRuntime: FATAL EXCEPTION: Thread-2 Process: com.raywenderlich.android.disneyexplorer, PID: 13419 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

Handler

Handler is a part of the HaMeR Framework (Handler, Message and Runnable). It allows you to send and process Message and Runnable objects. Every Handler instance is associated with a single thread and bound to that thread’s Looper. A message queue associated with a Looper can accept messages and runnables from Handler, which then execute on that looper’s thread. Handlers are commonly used in two scenarios:

val runnable = Runnable { // update the ui from here } val handler = Handler(Looper.getMainLooper()) handler.post(runnable) private fun runProcessingWithHandler() { // Create a Handler associated with the main thread val handler = Handler(Looper.getMainLooper()) // Create a new thread and give it some work to do Thread { val characters = disneyApiService.getDisneyCharacters() // Use the handler to show results on the main thread handler.post { showResults(characters) } }.start() }
Only the original thread that created a view hierarchy can touch its views Coroutine

HandlerThread

The UI thread already comes with a Looper and a MessageQueue. For other threads, you need to create the same objects if you want to leverage the HaMeR framework. Do this by extending the Thread class as follows:

// Preparing a Thread for HaMeR class MyLooperThread : Thread() { lateinit var handler: Handler override fun run() { // adding and preparing the Looper Looper.prepare() // the Handler instance will be associated with Thread’s Looper handler = object : Handler() { override fun handleMessage(msg: Message) { // process incoming messages here } } // Starting the message queue loop using the Looper Looper.loop() } } private fun runProcessingWithHandlerThread() { // Create a new thread handlerThread = HandlerThread("MyHandlerThread") handlerThread?.let { handlerThread?.start() // Create a new Handler that will use HandlerThread's Looper to do its work val handler = Handler(it.looper) // Create a Handler with the main thread Looper val mainHandler = Handler(Looper.getMainLooper()) // This will run on the HandlerThread created above handler.post { val characters = disneyApiService.getDisneyCharacters() // Use the handler associated with the main thread to show the results mainHandler.post { showResults(characters) } } } } private var processingMethod: ProcessingMethod = HANDLER_THREAD
Only the original thread that created a view hierarchy can touch its views Coroutine

Executors

The Executor interface helps to decouple submission of Runnable tasks from the mechanics of how each task will run, which thread will be used, how it will be scheduled, etc.

interface Executor { fun execute(command: Runnable) } interface Callable<T> { fun call(): T }

Sample Usage

val executor = Executors.newFixedThreadPool(4) (1..10).forEach { executor.submit { print("[Iteration $it] Hello from Kotlin Coroutines! ") println("Thread: ${Thread.currentThread()}") } }

This code sample is rather simple. First, it creates a new ExecutorService by using newFixedThreadPool(4). This creates a pool of four threads that will operate on the given tasks. Then, you create a range from 1 to 10 and iterate over it. In each iteration, you submit a new task that prints the current range value and the current thread’s name.

private fun runProcessingWithExecutor() { // Create a new Executor with a fixed thread pool and execute the Runnable val executor = Executors.newFixedThreadPool(1) executor.execute(getCharactersRunnable) }
Only the original thread that created a view hierarchy can touch its views Coroutine

RxJava

Reactive programming is an asynchronous programming paradigm concerned with data streams and change propagation. The essence of reactive programming is the observer pattern.

Sample Usage

Observable.just("Hello", "from", "RxJava") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(/* an Observer */);

This code creates a new Observable, which emits as a stream of three strings that are passed as arguments to just. subscribeOn specifies the values will be produced on a new thread, and observeOn means the observer will get the results on the main thread.

private fun runProcessingWithRxJava() { // 1 disposable = Single.create<List<DisneyCharacter>> { emitter -> // 2 val characters = disneyApiService.getDisneyCharacters() emitter.onSuccess(characters) // 3 }.subscribeOn(Schedulers.io()) // 4 .observeOn(AndroidSchedulers.mainThread()) // 5 .subscribe(::showResults, Throwable::printStackTrace) } // Dispose the disposable if it has been created disposable?.dispose()
Only the original thread that created a view hierarchy can touch its views Coroutine

Now that you have a clear idea about various ways of doing asynchronous work in Android, as well as some of the pros and cons, it’s time to come back to Kotlin coroutines. Kotlin coroutines are a way of doing things asynchronously in a sequential manner. Creating coroutines is quite cheap compared to creating threads.

// Coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0' private fun runProcessingWithCoroutines() { // Create a new coroutine in the scope tied to the lifecycle of the Activity lifecycleScope.launch(Dispatchers.IO) { // Make the network request on a background thread val characters = disneyApiService.getDisneyCharacters() // Switch to the main thread to show the results withContext(Dispatchers.Main) { showResults(characters) } } }
Only the original thread that created a view hierarchy can touch its views Coroutine

Key Points

  • Android is inherently asynchronous and event-driven, with strict requirements as to which thread certain things can happen on.
  • The UI thread — a.k.a., main thread — is responsible for interacting with the UI components and is the most important thread of an Android application.
  • Almost all code in an Android application will be executed on the UI thread by default. Blocking it would result in a non-responsive application state.
  • Thread is an independent path of execution within a program allowing for asynchronous code execution. But it’s highly complex to maintain and has usage limits.
  • Handler is a helper class provided by the Android SDK to simplify asynchronous programming. But it requires many moving parts to set up and get running.
  • HandlerThread is a thread that’s ready to receive a Handler because it has a Looper and a MessageQueue built into it.
  • Executors is a manager class that allows running many different tasks concurrently while sharing limited CPU time, used mainly to manage thread(s) efficiently.
  • RxJava is a library that makes it easier to implement reactive programming principles on the Android platform.
  • Coroutines make asynchronous code look synchronous and work pretty well with the Android platform out of the box.

Where to Go From Here?

Phew! That was a lot of background on asynchronous programming in Android. But the good thing is you made it.

15. Coroutines in the UI Layer 13. Testing Coroutines

How do you fix only the original thread that created a view hierarchy can touch its views?

To fix this error, wrap the code that has to be executed on UI thread in a Runnable instance passed to runOnUiThread() method.

Does coroutine run on main thread?

On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.

Does coroutine create new thread?

The launch function is a coroutine builder that starts a new coroutine without blocking the current thread and returns a reference to the coroutine as a Job object: runBlocking { val job = launch(Dispatchers.

What is a benefit of using coroutines over threads?

While doing things on your own managing thread pools manually is possible, coroutines is the recommended solution for asynchronous programming on Android due to the built-in cancellation support, easier error handling, structured concurrency which reduces the likelihood of memory leaks, and its integration with Jetpack ...