Skip to content

Instantly share code, notes, and snippets.

@vorobeij
Created November 21, 2018 12:53
Show Gist options
  • Save vorobeij/758d18bd69e7e5e39aa69eebc4d3ee1d to your computer and use it in GitHub Desktop.
Save vorobeij/758d18bd69e7e5e39aa69eebc4d3ee1d to your computer and use it in GitHub Desktop.
Android MVP multithreading with coroutines
package au.sjowl.coroutinesplay
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.lang.Exception
import kotlin.coroutines.CoroutineContext
class CommonHandler {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val interactor = Interactor()
val fragment = Fragment()
val presenter = HomePresenter(fragment, interactor)
runBlocking { presenter.loadData() }
}
}
}
interface BaseView {
fun showInternalError() = println("internal error")
fun showNoConnectionError() = println("no connection error")
fun showCommonError() = println("common error")
}
interface HomeView : BaseView {
fun showSuccess(data: String)
}
class Fragment : HomeView {
override fun showSuccess(data: String) = println("show successfully loaded data")
}
abstract class BasePresenter<V : BaseView>(
val view: V
) {
val exceptionHandler: CoroutineContext = CoroutineExceptionHandler { coroutineContext, throwable ->
when (throwable) {
is InternalError -> view.showInternalError()
is NoConnectionError -> view.showNoConnectionError()
else -> view.showCommonError()
}
}
// inject
val uiDispatcher = Dispatchers.Unconfined
val bgDispatcher = Dispatchers.IO
}
class HomePresenter(
// inject
fragment: HomeView,
val interactor: Interactor
) : BasePresenter<HomeView>(fragment) {
suspend fun loadData() = GlobalScope.launch(uiDispatcher + exceptionHandler) {
val data = async(bgDispatcher) { interactor.loadData() }
val data2 = async(bgDispatcher) { interactor.loadData2() }
view.showSuccess(data.await())
view.showSuccess(data2.await())
}.join()
}
class Interactor {
fun loadData(): String {
println(Thread.currentThread().name)
Thread.sleep(500)
return "success 1"
}
fun loadData2(): String {
println(Thread.currentThread().name)
Thread.sleep(300)
throw IllegalStateException("error 2")
}
}
open class ErrorWithCode(message: String, val code: Int) : Exception(message)
class InternalError(message: String, code: Int) : ErrorWithCode(message, code)
class NoConnectionError(message: String, code: Int) : ErrorWithCode(message, code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment