Skip to content

DataCode-Academy/android-kotlin-lesson9

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Android Kotlin Lesson 9 β€” Side-Effects & Performance

A comprehensive interactive Android app demonstrating advanced Jetpack Compose concepts including side-effects management and performance optimization techniques.

πŸ“š What You'll Learn

This lesson covers essential Compose concepts for production-ready apps:

  1. LaunchedEffect - Managing coroutines in Compose
  2. DisposableEffect - Handling cleanup with side effects
  3. derivedStateOf - Optimizing derived calculations
  4. snapshotFlow - Converting Compose State to Flow
  5. Performance Optimization - Avoiding unnecessary recompositions

🎯 Learning Objectives

  • Understand when and how to use different side-effect APIs
  • Master coroutine management in Compose lifecycle
  • Learn to optimize performance and prevent unnecessary recompositions
  • Implement proper cleanup for resources and observers
  • Use Flow operators with Compose state

πŸ“± Screenshots

Tab 1: LaunchedEffect Demo

LaunchedEffect

What it demonstrates:

  • How LaunchedEffect launches coroutines tied to composition lifecycle
  • Automatic restart when keys change
  • Timer implementation with pause/resume functionality
  • Interactive key switching (A, B, C) to see effect restart behavior

Key Concepts:

LaunchedEffect(key) {
    // This block restarts when 'key' changes
    while (isRunning) {
        delay(1000)
        counter++
    }
}

Tab 2: DisposableEffect Demo

DisposableEffect

What it demonstrates:

  • Lifecycle observation with proper cleanup
  • onDispose block for resource management
  • Toggle observer to see add/remove behavior
  • Real-time lifecycle event logging

Key Concepts:

DisposableEffect(lifecycle) {
    val observer = LifecycleEventObserver { _, event ->
        // Handle lifecycle events
    }
    lifecycle.addObserver(observer)
    
    onDispose {
        lifecycle.removeObserver(observer) // Cleanup!
    }
}

Tab 3: derivedStateOf Demo

derivedStateOf

What it demonstrates:

  • Optimizing derived calculations
  • Preventing unnecessary recompositions
  • Real-time recomposition counting
  • Interactive form with first name, last name, and age inputs

Key Concepts:

val fullName by remember { 
    derivedStateOf { "$firstName $lastName" } 
}
// Only recomposes when the RESULT changes, not on every keystroke

Tab 4: snapshotFlow Demo

snapshotFlow

What it demonstrates:

  • Converting Compose State to Kotlin Flow
  • Scroll position tracking
  • Flow operators (distinctUntilChanged, map, filter)
  • Scroll-to-top FAB that appears when not at top

Key Concepts:

LaunchedEffect(listState) {
    snapshotFlow { listState.firstVisibleItemIndex }
        .distinctUntilChanged()
        .collect { index ->
            // React to scroll changes
        }
}

Tab 5: Performance Optimization Demo

Performance

What it demonstrates:

  • Side-by-side comparison of optimized vs unoptimized code
  • Real-time recomposition counting
  • Impact of remember() with keys
  • Visual demonstration of performance differences

Key Concepts:

// ❌ Bad: Recalculates every recomposition
val result = expensiveCalculation(input)

// βœ“ Good: Only recalculates when input changes
val result = remember(input) { 
    expensiveCalculation(input) 
}

πŸ› οΈ Technical Details

Dependencies

implementation("androidx.lifecycle:lifecycle-runtime-compose:2.9.4")
implementation("androidx.activity:activity-compose:1.11.0")
implementation("androidx.compose.material3:material3")

Requirements

  • Min SDK: 26 (Android 8.0)
  • Target SDK: 36
  • Kotlin: 2.0.21
  • Compose BOM: 2024.09.00

πŸ—οΈ Project Structure

app/src/main/java/com/example/androidkotlinlesson9/
β”œβ”€β”€ MainActivity.kt              # Entry point
β”œβ”€β”€ SideEffectsLesson.kt        # All lesson composables
└── ui/theme/                   # Theme configuration

πŸŽ“ Key Takeaways

1. LaunchedEffect

  • Use for: API calls, timers, animations, one-time events
  • Lifecycle: Cancels when leaving composition
  • Key parameter: Restarts effect when key changes

2. DisposableEffect

  • Use for: Observers, listeners, resource registration
  • Cleanup: Always implement onDispose block
  • Remember: Cleanup is crucial to prevent memory leaks

3. derivedStateOf

  • Use for: Computed properties, derived calculations
  • Performance: Only recomposes when result changes
  • Best practice: Wrap in remember for optimal performance

4. snapshotFlow

  • Use for: Analytics, scroll tracking, state monitoring
  • Power: Full Flow API with operators
  • Integration: Bridges Compose State with coroutines

5. Performance Optimization

  • remember(): Cache expensive calculations
  • keys: Provide keys to control recalculation
  • Stable parameters: Use immutable data classes
  • Avoid: Lambda allocations in tight loops

πŸš€ Running the Project

  1. Clone the repository
  2. Open in Android Studio (Ladybug | 2024.2.1 or later)
  3. Sync Gradle dependencies
  4. Run on emulator or physical device (Android 8.0+)
  5. Explore each tab to learn interactively

πŸ’‘ Tips for Learning

  1. Experiment: Try changing keys in LaunchedEffect tab
  2. Observe: Watch recomposition counts in Performance tab
  3. Compare: Notice the difference between optimized and unoptimized code
  4. Read logs: Check Logcat for DisposableEffect and snapshotFlow events
  5. Modify: Change the code and see immediate results

🎯 Practice Exercises

  1. Add a new LaunchedEffect that fetches data from an API
  2. Create a DisposableEffect for keyboard visibility listener
  3. Implement derivedStateOf for filtering a list
  4. Use snapshotFlow to track text field changes
  5. Optimize a slow list with proper keys and stable parameters

πŸ“– Additional Resources

πŸ› Common Pitfalls to Avoid

  1. Don't: Use LaunchedEffect(true) - it never restarts
  2. Don't: Forget onDispose in DisposableEffect
  3. Don't: Call expensive functions directly in Composables
  4. Don't: Use mutable state outside of remember
  5. Do: Always provide meaningful keys to side effects

πŸ” What Makes This Lesson Unique

  • Interactive Learning: Each concept has hands-on examples
  • Visual Feedback: Real-time recomposition counters
  • Real-world Examples: Practical use cases for each API
  • Performance Comparison: See the impact of optimization
  • Best Practices: Learn the right way from the start

πŸ“ Code Highlights

Smart Timer Implementation

The LaunchedEffect demo shows a production-ready timer that:

  • Restarts when key changes
  • Can be paused/resumed
  • Properly cancels on composition exit
  • Logs lifecycle events for debugging

Lifecycle Observer Pattern

The DisposableEffect demo demonstrates:

  • Proper observer registration/unregistration
  • Memory leak prevention
  • Event logging for debugging
  • Clean separation of concerns

Recomposition Tracking

The Performance demo uses SideEffect to:

  • Count recompositions per component
  • Compare optimization strategies
  • Visualize performance impact
  • Teach optimization techniques

🎨 UI/UX Features

  • Material 3 Design: Modern, clean interface
  • Tab Navigation: Easy switching between lessons
  • Color-coded Cards: Visual distinction of concepts
  • Interactive Controls: Buttons, sliders, text fields
  • Responsive Layout: Works on all screen sizes
  • Smooth Animations: AnimatedVisibility for polish

πŸ”§ Build Configuration

The project uses:

  • Kotlin DSL for build scripts
  • Version Catalog for dependency management
  • Compose Compiler Plugin for optimization
  • ProGuard rules for release builds

πŸ“Š Learning Metrics

After completing this lesson, you should be able to:

  • βœ… Choose the right side-effect API for your use case
  • βœ… Implement proper cleanup in your Composables
  • βœ… Optimize performance and reduce recompositions
  • βœ… Debug composition and recomposition issues
  • βœ… Write production-ready Compose code

🌟 Next Steps

  1. Practice: Build a feature using each side-effect API
  2. Experiment: Modify the examples to test edge cases
  3. Profile: Use Layout Inspector to see recompositions
  4. Optimize: Apply learnings to your existing projects
  5. Share: Teach others what you've learned

πŸ“§ Feedback & Contributions

Found a bug? Have a suggestion? Feel free to:

  • Open an issue
  • Submit a pull request
  • Share your improvements

Happy Coding! πŸš€

Made with ❀️ using Jetpack Compose

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages