
Compare Java and Kotlin for Android development, highlighting identical memory and threading models and seamless interoperability. Emphasize Java in the course while Kotlin materials apply equally, except for coroutines.
Explore building the tutorial app, including demonstrations and ten exercises, and learn to manage memory and threads to prevent crashes while adjusting the default configuration, factorial timeout, and GitHub link.
Explore single-tasking systems where the CPU executes one program at a time under the operating system, with the program counter tracking progress until termination.
Explore cooperative multitasking, where tasks yield to release CPU resources and are resumed later from the yield point, enabling concurrent execution, yet requiring cooperation to prevent system stalls.
Explore preemptive multitasking systems where the operating system schedules tasks, pausing and resuming them to achieve apparent concurrent execution. See how this design ensures responsiveness on Android while managing complexity.
Explore multiprocessing systems with multiple cores inside a central processing unit and how the operating system coordinates concurrent tasks to enable true parallelism, while distinguishing concurrency from parallelism.
Explore the java.lang.Thread class and two instantiation approaches: extending Thread with a run method or passing a Runnable to a new Thread. Emphasize composition over inheritance and start the Thread.
Run exercise 1 to see how counting iterations on the main thread causes frame drops and ANR, then move countIterations to a new thread to fix the UI freeze.
Explore how memory allocation creates objects and how the Android garbage collector automatically reclaims non-reachable objects by tracing roots and references, including handling circular references and onDestroy behavior.
Understand memory leaks in Android by tracing object reachability from roots, including static references, application class, and live threads, and how anonymous and inner threads hold activities.
Terminate threads by allowing run to complete. Alternatively, abort on error, honor an externally set flag, or respond to interruption; prefer external flags to interruptions, as shown with OkHttp.
Practice fixing a memory leak in the exercise two fragment by terminating the background thread on stop, using an atomic boolean to stop the thread, preventing out of memory errors.
Understand how the Android thread class creates single in-process tasks, why starting threads makes them garbage collection roots, and how anonymous and inner class references can cause memory leaks.
Learn how the Android UI thread, or main thread, handles lifecycle events and user interactions. Run UI manipulations on this thread; background threads are any threads not UI thread.
Offload time-consuming tasks to background threads to preserve user interface responsiveness and achieve smooth 60 fps rendering. Monitor for skipped frames and not responding warnings, and test on reasonable devices.
Learn to protect the user interface from background threads by ensuring UI updates run on the UI thread, avoiding wrong-thread exceptions, and preparing to transfer work back to the UI.
Explore how handler and looper concepts underpin a background worker thread by using a blocking queue to execute runnable jobs sequentially, with a poison data item to stop.
Offload counting to a background thread and update the UI thread via a handler and looper to display the seconds counter. Disable the button during counting, show done, then re-enable.
Understand that the UI thread in Android is a looper that processes runnables. Offload long tasks to background threads and perform UI updates on the UI thread.
Explore the fundamental challenges of multithreading in Android, including preemptive multitasking and shared state risks. Learn the three thread safety concerns—visibility, atomicity, and happens before—with emphasis on the complexity.
Explore visibility issues in multithreaded Java programs with a producer and consumer example that shows how cached local state within the thread can prevent updates from being seen, causing hangs.
Explore atomicity violations when 100 threads concurrently increment a volatile shared state counter, revealing non-atomic read-modify-write operations and race conditions that degrade data integrity.
Make code thread safe by using volatile variables to ensure visibility across threads by going directly to main memory, recognizing volatile does not guarantee atomicity and may affect readability.
Diagnose a producer–consumer concurrency bug where volatile fixes visibility but not atomicity. Learn how sampling the shared counter can mask issues and why manual synchronization is often needed.
Learn how atomic variables, especially atomic integer, guarantee atomicity and thread safe increments using get and increment, while volatile ensures visibility across threads. Explore compare and set for advanced synchronization.
Synchronize producer and consumer threads using a shared lock to guarantee atomicity and visibility, replacing volatile with synchronized blocks and a single lock for thread-safe reads and writes.
Learn how immutability and finalization improve thread safety by using atomic integers, volatile references, and final fields to prevent lost increments and visibility issues in Android multithreading.
Examine the happens-before concept with a Java producer–consumer demo, showing how volatile and synchronization ensure visibility, and why thread safety does not guarantee functional correctness or atomicity.
Explore exercise four to implement and debug a parallel factorial calculator in the fragment, using multiple threads, timeouts, and thread-safety review to ensure correctness.
Explore a practical multithreading solution by auditing shared state, ensuring thread safety with final, volatile, and atomic constructs, and applying happens-before reasoning to protect UI and worker threads.
Reveal why volatile alone fails for visibility and demonstrate how an atomic variable creates a happens-before edge that ensures thread-safe results in exercise 4.
Explore the two core multithreading challenges on the JVM—happens-before relationships and atomicity—through synchronization, volatile semantics, atomic classes, and thread coordination to ensure thread safety in Android apps.
Discover why pausing threads helps create progress delays, wait for asynchronous input, and coordinate multiple threads, and why busy waiting is costly and should be avoided.
Learn how to coordinate threads by waiting on a shared lock with wait and notify all, handling asynchronous events and timeouts without using sleep.
Learn how thread join makes the main thread wait for a producer thread to terminate, observe a happens-before relationship, and compare join with wait/notify as synchronization options.
Identify a multithreading bug and fix it with proper synchronization and visibility. Move thread starts outside critical sections, use a while loop for waits, and prefer join over notifications.
Practice with 1000 producer and 1000 consumer threads using a custom blocking queue, implement synchronization to count finished messages, and display execution time and results.
Demonstrate a blocking queue solution with synchronized put and take, using a queue lock and notify all to coordinate threads, and provide insights into Android device performance.
Emphasize that clean design in multithreaded code is crucial, often more important than code itself. Learn a practical, instructor-backed approach to clean multithreaded design, prioritizing thread safety and coordinating threads.
Refactor multi-threaded Android code by extracting a producer-consumer benchmark into a use case, implement an observer pattern, and delegate UI responsibilities to the fragment while lifecycle-aware observers manage notifications.
Practice extracting a use case from the multithreaded fragment, move factorial computation logic into it, and implement cancellation via a use case method or last listener abort signals.
Explore how thread pool configurations can cause memory errors. See why fixed size and cached pools may fail under heavy workloads and blocking queues.
Explore how misconfiguring a thread pool executor backing async tasks leads to rejected executions and performance issues, and why developers should avoid manual configuration of thread pools.
Centralizes a thread pool via dependency injection to provide a shared resource for a producer-consumer benchmark use case, with composition roots managing dependencies and a UI handler.
Refactor compute factorial use case to use the thread pool in the application composition route and inject the UI handler via its constructor. Explore thread pool configurations to optimize concurrency.
Learn why you should avoid async task in new projects, compare it to thread pools, and uncover common misconceptions about memory leaks and how async task works.
Demonstrate using Android async task to replace bare threads, detailing doInBackground, onPreExecute, and onPostExecute, while warning about thread pool misconfiguration and memory-leak risks.
Assess the drawbacks of Android async task, including inheritance dependence and a complex API. Discover why other solutions handle concurrency better for new code.
Discover Thread Poster, a lightweight multithreading library with UI thread poster and background thread poster for refactoring bare threads into a post-based model, using three core threads, a synchronous queue, and unlimited threads.
Replace manual threading in the compute factorial use case with a thread poster, and augment the dependencies graph with UI thread poster and background thread poster from the composition route.
Explain why thread poster provides explicit naming and a simple API compared to thread pool executor and handler. Highlight its suitability for multi-threaded unit testing and the trade-offs.
Multithreading is an essential topic in Android development because, to write snappy and reliable Android applications, you must use more than one thread. Unfortunately, multithreading is also a very complex technique that introduces unique challenges. Incorrect multithreaded code manifests itself as unresponsive user interfaces, freezes, memory leaks, crashes and other bugs, all of which can be very challenging to find and fix.
In this course, you'll dive into the fundamentals of multithreading and learn to write correct and performant multithreaded code of any complexity in your Android applications!
Topics covered in this course:
What a thread is
Why multithreading is uniquely challenging
Keep the user interface responsive
Make your multithreaded code thread-safe (i.e. correct and reliable)
Analyze the performance of multithreaded code
Manage up to hundreds(!) of concurrent threads
Compare several multithreading frameworks for Android, including AsyncTask, RxJava and Kotlin Coroutines
More...
You'll practice everything you'll learn here by solving a series of carefully designed, hands-on exercises. So, after completing this course, you'll have extensive hands-on experience with multithreaded code.
We'll review several popular concurrency frameworks and see how they accommodate the same complex multithreaded feature. This will allow you to grasp the full landscape of multithreading in Android ecosystem. This will allow you to choose the framework you like the best to use in your Android projects!
So, if you want to become an expert in Android multithreading, this course is perfect for you!