14. object RetrofitFactory {
const val BASE_URL = "https://sample.com"
fun makeRetrofitService(): RetrofitService {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build().create(RetrofitService::class.java)
}
}
Building Retrofit Service
15. class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val service = RetrofitFactory.makeRetrofitService()
GlobalScope.launch(Dispatchers.Main) {
val request = service.getPosts()
try {
val response = request.await()
// Do something with the response.
} catch (e: HttpException) {
toast(e.code())
} catch (e: Throwable) {
toast("Ooops: Something else went wrong")
}
}
}
Bringing it all together
21. public object GlobalScope : CoroutineScope {
/**
* Returns [EmptyCoroutineContext].
*/
override val coroutineContext: CoroutineContext
get() = EmptyCoroutineContext
}
22. public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
....
}
23. suspend fun delay(timeMillis: Long): Unit (source)
Delays coroutine for a given time without blocking a thread and
resumes it after a specified time. This suspending function is
cancellable.
24.
25. Declare functions with their parameters and
return values.
• (Int) -> String
• () -> String
• (Int, Int) -> String
• () -> () -> String
26. var print: (Int) -> String
• var printHello: () -> String
• Var printNumbers: (Int, Int) -> String
28. public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
....
}
29. Suspending functions can be used inside coroutines just like regular
functions, but their additional feature is that they can, in turn, use other
suspending functions.
35. fun main() = runBlocking {
launch {
printWorld()
}
println("Hello,")
}
private suspend fun printWorld() {
delay(1000L)
println("World!")
}
36.
37. • JVM Options: -Dkotlinx.coroutines.debug
• Get thread name: Thread.currentThread().name
38. fun main() = runBlocking<Unit> {
val a = async {
log("I'm computing a piece of the answer")
6
}
val b = async {
log("I'm computing another piece of the answer")
7
}
log("The answer is ${a.await() * b.await()}")
}
39. [main @coroutine#2] I'm computing a piece of the answer
[main @coroutine#3] I'm computing another piece of the answer
[main @coroutine#1] The answer is 42
43. Sequential by default
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
val one = doSomethingUsefulOne()
val two = doSomethingUsefulTwo()
println("The answer is ${one + two}")
}
println("Completed in $time ms")
}
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here, too
return 29
}
46. public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T> {
....
}
public fun CoroutineScope.launch(
context: CoroutineContext =
EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
....
}
47. Concurrent using async
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful here
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here
return 29
}
48.
49. public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
....
}
51. fun main() = runBlocking<Unit> {
launch {
println("main runBlocking : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Unconfined) {
println("Unconfined : I'm working in thread ${Thread.currentThread().name}")
}
launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher
println("Default : I'm working in thread ${Thread.currentThread().name}")
}
launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}")
}
}
52. Unconfined : I'm working in thread main @coroutine#3
Default : I'm working in thread DefaultDispatcher-worker-1 @coroutine#4
newSingleThreadContext: I'm working in thread MyOwnThread @coroutine#5
main runBlocking : I'm working in thread main @coroutine#2