fun doHttpRequest( callback: (X) -> Unit ) {
// A long running operation
...
callback(X)
}
Slide 26
Slide 26 text
suspend fun doHttpRequest(): X {
// A long running operation
...
return X
}
Slide 27
Slide 27 text
launch {
val a = doHttpRequest()
val b = doHttpRequest()
val c = doHttpRequest()
val d = doHttpRequest()
val e = doHttpRequest()
val f = doHttpRequest()
val g = doHttpRequest()
}
Slide 28
Slide 28 text
suspend fun doHttpRequest(): X {
// A long running operation
...
return X
}
Slide 29
Slide 29 text
fun doHttpRequest(continuation : Continuation) {
// A long running operation
...
}
Slide 30
Slide 30 text
fun doHttpRequest(continuation : Continuation) {
// A long running operation
...
contination.resume(X)
}
Slide 31
Slide 31 text
fun doHttpRequest( callback: (X) -> Unit ){
// A long running operation
...
callback(X)
}
Slide 32
Slide 32 text
fun doHttpRequest( observer: (X) -> Unit ){
// A long running operation
...
observer(X)
}
Slide 33
Slide 33 text
Observer Pattern
Slide 34
Slide 34 text
fun doHttpRequest( observer: (X) -> Unit ){
// A long running operation
...
observer(X)
}
Slide 35
Slide 35 text
fun downloadVideo( observer: (progress) -> Unit ) {
}
Slide 36
Slide 36 text
fun downloadVideo( observer: (progress) -> Unit ) {
// A long running operation
...
observer(0.1)
...
observer(0.2)
...
observer(1.0)
}
Slide 37
Slide 37 text
suspend fun downloadVideo() : ??? {
// A long running operation
...
???
}
With Coroutines?
Slide 38
Slide 38 text
fun downloadVideo( observer: (progress) -> Unit )
Slide 39
Slide 39 text
interface Downloader {
fun downloadVideo( observer: (progress) -> Unit )
}
Slide 40
Slide 40 text
interface Downloader {
fun download( observer: (progress) -> Unit )
}
Slide 41
Slide 41 text
interface Downloader {
fun download( observer: (T) -> Unit )
}
Slide 42
Slide 42 text
interface Downloader {
fun download( observer: (T) -> Unit )
}
interface DownloadObserver
Slide 43
Slide 43 text
interface Downloader {
fun download( observer: (T) -> Unit )
}
interface DownloadObserver {
fun emit( value: T )
}
Slide 44
Slide 44 text
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
Slide 45
Slide 45 text
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
Slide 46
Slide 46 text
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
interface Downloader {
fun collect( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
Slide 47
Slide 47 text
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
interface Downloader {
fun collect( c: Collector )
}
interface Collector {
fun emit( value: T )
}
Slide 48
Slide 48 text
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
interface Flow {
fun collect( c: Collector )
}
interface Collector {
fun emit( value: T )
}
Slide 49
Slide 49 text
interface Downloader {
fun download( o: DownloadObserver )
}
interface DownloadObserver {
fun emit( value: T )
}
interface Flow {
fun collect( c: FlowCollector )
}
interface FlowCollector {
fun emit( value: T )
}
Slide 50
Slide 50 text
interface Flow {
fun collect( c: FlowCollector )
}
interface FlowCollector {
fun emit( value: T )
}
Flow
Slide 51
Slide 51 text
interface Flow {
suspend fun collect( c: FlowCollector )
}
interface FlowCollector {
suspend fun emit( value: T )
}
Flow
Slide 52
Slide 52 text
fun downloadVideo(): ??? {
...
???
}
Slide 53
Slide 53 text
fun downloadVideo(): Flow {
...
???
}
Slide 54
Slide 54 text
fun flow(block: suspend FlowCollector.() -> Unit): Flow
fun downloadVideo(): Flow {
...
???
}
Slide 55
Slide 55 text
fun flow(block: suspend FlowCollector.() -> Unit): Flow
fun downloadVideo(): Flow = flow {
...
???
}
Slide 56
Slide 56 text
fun flow(block: suspend FlowCollector.() -> Unit): Flow
fun downloadVideo(): Flow = flow {
// this: FlowCollector
...
???
}
Slide 57
Slide 57 text
fun flow(block: suspend FlowCollector.() -> Unit): Flow
fun downloadVideo(): Flow = flow {
// this: FlowCollector
...
emit(0.1)
}
Slide 58
Slide 58 text
fun flow(block: suspend FlowCollector.() -> Unit): Flow
fun downloadVideo(): Flow = flow {
// this is FlowCollector
...
emit(0.1)
...
emit(0.2)
...
emit(1.0)
}
Slide 59
Slide 59 text
Let it Flow!
Slide 60
Slide 60 text
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}
Slide 61
Slide 61 text
class MyViewModel : ViewModel() {
init {
viewModelScope.launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}
}
}
}
Slide 62
Slide 62 text
class MyViewModel : ViewModel() {
init {
viewModelScope.launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}
}
}
}
Launch new coroutine
Slide 63
Slide 63 text
class MyViewModel : ViewModel() {
init {
viewModelScope.launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}
}
}
}
Launch new coroutine
2.1.0-beta01
Slide 64
Slide 64 text
class MyViewModel : ViewModel() {
init {
viewModelScope.launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}
}
}
}
Suspending block
executed in coroutine
Slide 65
Slide 65 text
launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}
}
Slide 66
Slide 66 text
launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}.collect { value ->
println(value)
}
}
Slide 67
Slide 67 text
launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}.collect { value ->
println(value)
}
}
Observes flow
Slide 68
Slide 68 text
launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}.collect { value ->
println(value)
}
}
notify observer
about value
Slide 69
Slide 69 text
launch {
flow {
for (i in 0..5) {
delay(100)
emit(i)
}
}.collect { value ->
println(value)
}
}
Slide 70
Slide 70 text
What about errors?
Slide 71
Slide 71 text
flow {
throw Exception("Something went wrong")
}.collect {
println(it)
}
interface CoroutineContext
interface Job : CoroutineContext {
public fun cancel(): Unit
// a lot more…
}
Slide 133
Slide 133 text
interface CoroutineContext
interface Job : CoroutineContext {
public fun cancel(): Unit
// a lot more…
}
abstract class CoroutineDispatcher
Slide 134
Slide 134 text
interface CoroutineContext
interface Job : CoroutineContext {
public fun cancel(): Unit
// a lot more…
}
abstract class CoroutineDispatcher
Dispatchers.Main
Dispatchers.Default
Dispatchers.IO
Dispatchers.Unconfined
newSingleThreadContext()
Slide 135
Slide 135 text
interface CoroutineContext
interface Job : CoroutineContext {
public fun cancel(): Unit
// a lot more…
}
abstract class CoroutineDispatcher
Dispatchers.Main
Dispatchers.Default
Dispatchers.IO
Dispatchers.Unconfined
newSingleThreadContext()
val context: CoroutineContext = Job() + Dispatchers.IO
Slide 136
Slide 136 text
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
Slide 137
Slide 137 text
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
public inline fun CoroutineScope.cancel()
Slide 138
Slide 138 text
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
public inline fun CoroutineScope.cancel()
public fun CoroutineScope.launch(...)
Slide 139
Slide 139 text
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
public inline fun CoroutineScope.cancel()
public fun CoroutineScope.launch(...)
val ViewModel.viewModelScope: CoroutineScope
val Lifecycle.coroutineScope: LifecycleCoroutineScope
Threading
• collect lambda is always called on the initial CoroutineContext
Slide 170
Slide 170 text
Threading
• collect lambda is always called on the initial CoroutineContext
• flowOn does only influence the upstream
Slide 171
Slide 171 text
Threading
• collect lambda is always called on the initial CoroutineContext
• flowOn does only influence the upstream
• nothing can change the context of downstream emissions
val someFunction: (() -> Result) = ...
someFunction.asFlow()
Slide 178
Slide 178 text
val someFunction: (() -> Result) = ...
someFunction.asFlow()
val doHttpRequest: (suspend () -> Result) = ...
Slide 179
Slide 179 text
val someFunction: (() -> Result) = ...
someFunction.asFlow()
val doHttpRequest: (suspend () -> Result) = ...
doHttpRequest.asFlow()
Slide 180
Slide 180 text
val observable: Observable = Observable.just(1)
Slide 181
Slide 181 text
val observable: Observable = Observable.just(1)
val flow: Flow = observable.toFlowable().asFlow()
Slide 182
Slide 182 text
val observable: Observable = Observable.just(1)
val flow: Flow = observable.toFlowable().asFlow()
val observable2: Observable = flow.asPublisher().toObservable()
interface MyService {
@GET(“{user}/books/favorite”)
suspend fun getFavoriteBook(@Path(“user") userId: Int): Book
}
Slide 186
Slide 186 text
new
in
2.6.0
interface MyService {
@GET(“{user}/books/favorite”)
suspend fun getFavoriteBook(@Path(“user") userId: Int): Book
}
Slide 187
Slide 187 text
flow {
emit(userId1)
emit(userId2)
}
interface MyService {
@GET("{user}/books/favorite")
suspend fun getFavoriteBook(@Path("user") userId: Int): Book
}
Slide 188
Slide 188 text
flow {
emit(userId1)
emit(userId2)
}.someOperator { userId ->
val book = myService.getFavoriteBook(userId)
book
}
interface MyService {
@GET("{user}/books/favorite")
suspend fun getFavoriteBook(@Path("user") userId: Int): Book
}
Slide 189
Slide 189 text
flow {
emit(userId1)
emit(userId2)
}.someOperator { userId ->
val book = myService.getFavoriteBook(userId)
book
}.collect { book ->
println(book)
}
interface MyService {
@GET("{user}/books/favorite")
suspend fun getFavoriteBook(@Path("user") userId: Int): Book
}
Slide 190
Slide 190 text
flow {
emit(userId1)
emit(userId2)
}.map { userId ->
val book = myService.getFavoriteBook(userId)
book
}.collect { book ->
println(book)
}
interface MyService {
@GET("{user}/books/favorite")
suspend fun getFavoriteBook(@Path("user") userId: Int): Book
}