Introduction
- Who is this book for?
- The structure of this book
- What will be covered?
- The Kotlin for Developers series
- Conventions
- Code conventions
- Version
- Exercises and solutions
- Acknowledgments
Part 1: Understanding Kotlin Coroutines
Why Kotlin Coroutines?
- Simplicity
- Performance
- Cancellation
- Synchronization
- Testability
- Flow
- Coroutines are multiplatform
- The biggest problem with Kotlin Coroutines
- Summary
Sequence builder
- Real-life usages
- Exercise: Factorial sequence
- Exercise: Prime numbers sequence
How does suspension work?
- A game analogy
- Suspending functions
- Your first suspension
- What is stored in the continuation?
- Delaying a coroutine
- Resuming with a value
- Resume with an exception
- Suspending a coroutine, not a function
- Summary
- Exercise: Callback function wrappers
- Exercise: Continuation storage
Coroutines under the hood
- Continuation-passing style
- A very simple function
- A function with a state
- A function resumed with a value
- The call stack
- Suspending functions in other contexts
- The actual code
- The performance of suspending functions
- Summary
- Exercise: What is stored by a continuation?
Coroutines: built-in support vs library
Part 2: Kotlin Coroutines library
Starting coroutines
- Asynchronous coroutine builders
- Blocking coroutine builders
- Structured Concurrency
- Coroutine scope functions
- Summary
- Exercise: UserDetailsRepository
- Exercise: BestStudentUseCase
- Exercise: CommentService
- Exercise: mapAsync
The bigger picture
Coroutine context
CoroutineContextinterface- Finding elements in CoroutineContext
- Adding contexts
- Empty coroutine context
- Subtracting elements
- Folding context
- Coroutine context and builders
- Accessing context in a suspending function
- Changing context in suspending functions
- Creating our own context
- Coroutines and thread elements
- Summary
- Exercise: Understanding context propagation
- Exercise: CounterContext
Dispatchers
- Default dispatcher
- Limiting the default dispatcher
- Main dispatcher
- IO dispatcher
- Dispatcher with a custom limit
- Dispatcher with a fixed pool of threads
- Dispatcher limited to a single thread
- Using virtual threads from Project Loom
- Unconfined dispatcher
- Immediate main dispatching
- Continuation interceptor
- Performance of dispatchers when executing different tasks
- Summary
- Exercise: Using dispatchers
- Exercise: DiscNewsRepository
- Exercise: Experiments with dispatchers
Job and coroutine lifecycle
- Job and relationships
- Coroutine lifecycle
- Awaiting job completion
- The Job factory function
- Synchronizing coroutines
- Summary
Cancellation
- Basic cancellation
- The
finallyblock - invokeOnCompletion
- Cancellation of children
- Cancellation in a coroutine scope
- Just one more call
- Stopping the unstoppable
- CancellationException is special
- CancellationException does not propagate to its parent
- withTimeout
suspendCancellableCoroutine- Summary
- Exercise: Correct mistakes with cancellation
Exception handling
- Exceptions and structured concurrency
- SupervisorJob
- supervisorScope
- Exceptions and await call
CoroutineExceptionHandler- Summary
Constructing a coroutine scope
- CoroutineScope factory function
- Constructing a background scope
- Constructing a scope on Android
- Summary
- Exercise: NotificationSender
- Exercise: BaseViewModel
Synchronizing access to mutable state
- Using atomic values
- Synchronized blocks
- Using a dispatcher limited to a single thread
- Mutex
- Semaphore
- Summary
- Exercise: CompanyDetailsRepository
- Exercise: CancellingRefresher
- Exercise: TokenRepository
- Exercise: Suspended lazy
- Exercise: mapAsync with concurrency limit
Testing Kotlin Coroutines
- Testing time dependencies
TestCoroutineSchedulerandStandardTestDispatcher- runTest
- Background scope
- Testing cancellation and context passing
UnconfinedTestDispatcher- Using mocks
- Testing functions that change a dispatcher
- Testing what happens during function execution
- Testing functions that launch new coroutines
- Testing classes that need scope in runTest
- Replacing the main dispatcher
- Testing Android functions that launch coroutines
- Setting a test dispatcher with a rule
- Summary
- Exercise: Test UserDetailsRepository
- Exercise: Testing mapAsync
- Exercise: Testing the NotificationSender class
- Exercise: Testing a View Model
Part 3: Channel and Flow
Channel
- Channel types
- On buffer overflow
- On undelivered element handler
- Fan-out
- Fan-in
- Pipelines
- Practical usage
- Summary
- Exercise: UserRefresher
- Exercise: Cafeteria simulation
Select
- Selecting deferred values
- Selecting from channels
- Summary
- Exercise: raceOf
Hot and cold data sources
- Hot vs cold
- Hot channels, cold flow
- Summary
Flow introduction
- Comparing flow to other ways of representing values
- The characteristics of Flow
- Flow nomenclature
- Real-life use cases
- Summary
Understanding Flow
- Understanding
Flow - How
Flowprocessing works - Flow is synchronous
- Flow and shared state
- Conclusion
Flow building
- Flow from raw values
- Converters
- Converting a function to a flow
- Flow and Reactive Streams
- Flow builders
- Understanding flow builder
- channelFlow
- callbackFlow
- Summary
- Exercise: Flow utils
- Exercise: All users flow
- Exercise: distinct
Flow lifecycle functions
- onEach
- onStart
- onCompletion
- onEmpty
- catch
- Uncaught exceptions
retry- flowOn
- launchIn
- Summary
- Exercise: TemperatureService
- Exercise: NewsViewModel
Flow processing
mapfiltertakeanddrop- How does collection processing work?
merge,zipandcombinefoldandscanflatMapConcat,flatMapMergeandflatMapLatest- Distinct until changed
bufferandconflatedebouncesample- Terminal operations
- Summary
- Exercise: ProductService
- Exercise: Flow Kata
- Exercise: MessageService
SharedFlow and StateFlow
- SharedFlow
shareIn- StateFlow
stateIn- Summary
- Exercise: Update ProductService
- Exercise: Update TemperatureService
- Exercise: LocationService
- Exercise: PriceService
- Exercise: NewsViewModel using stateIn
Testing flow
- Transformation functions
- Testing infinite flows
- Determining how many connections were opened
- Testing view models
- Summary
- Exercise: Flow testing
Part 4: Kotlin Coroutines in practice
Common use cases
- Data/Adapters Layer
- Domain Layer
- Presentation/API/UI layer
- Summary
Using coroutines from other languages
- Threads on different platforms
- Transforming suspending into non-suspending functions
- Calling suspending functions from other languages
- Flow and Reactive Streams
- Summary
