kotlin
106 lines · 1 tab
Alex Chen
Jan 2026
1 tab
package com.example.myapp.ui.detail
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class PostDetailViewModel @Inject constructor(
private val repository: PostRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
private val postId: Int = savedStateHandle.get<Int>("postId") ?: 0
private val _uiState = MutableStateFlow(PostDetailUiState())
val uiState: StateFlow<PostDetailUiState> = _uiState.asStateFlow()
init {
loadPost()
loadComments()
}
private fun loadPost() {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
repository.getPost(postId)
.onSuccess { post ->
_uiState.update {
it.copy(
post = post,
isLoading = false,
isLiked = post.likedByCurrentUser
)
}
}
.onFailure { e ->
_uiState.update {
it.copy(error = e.message, isLoading = false)
}
}
}
}
private fun loadComments() {
viewModelScope.launch {
repository.getComments(postId)
.collect { comments ->
_uiState.update { it.copy(comments = comments) }
}
}
}
fun toggleLike() {
viewModelScope.launch {
val currentState = _uiState.value
// Optimistic update
_uiState.update {
it.copy(
isLiked = !currentState.isLiked,
likesCount = if (currentState.isLiked)
currentState.likesCount - 1
else
currentState.likesCount + 1
)
}
repository.toggleLike(postId)
.onFailure {
// Rollback on error
_uiState.update {
it.copy(
isLiked = currentState.isLiked,
likesCount = currentState.likesCount
)
}
}
}
}
fun addComment(text: String) {
viewModelScope.launch {
repository.createComment(postId, text)
.onSuccess {
loadComments()
}
.onFailure { e ->
_uiState.update { it.copy(error = e.message) }
}
}
}
}
data class PostDetailUiState(
val post: Post? = null,
val comments: List<Comment> = emptyList(),
val isLoading: Boolean = false,
val isLiked: Boolean = false,
val likesCount: Int = 0,
val error: String? = null
)
1 file · kotlin
Explain with highlit
MVVM separates concerns in Android apps—Model holds data, View displays UI, ViewModel mediates with business logic. ViewModels survive configuration changes, preventing data loss during rotation. I use ViewModel class with viewModelScope for coroutines. LiveData or StateFlow expose observable state to UI. Views observe changes with observe() or collectAsState(). Repository pattern abstracts data sources—network and database. Dependency injection with Hilt provides ViewModels. The ViewModel never holds Activity/Fragment references to avoid memory leaks. Use SavedStateHandle for process death survival. This architecture makes code testable, maintainable, and follows Android's recommended patterns.
Related snips
kotlin
package com.example.myapp
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
Dependency injection with Hilt
kotlin
android
hilt
by Alex Chen
3 tabs
kotlin
package com.example.myapp.ui
import androidx.lifecycle.*
import kotlinx.coroutines.launch
class UserViewModel(
LiveData transformations and mediators
kotlin
android
livedata
by Alex Chen
1 tab
kotlin
package com.example.myapp.utils
import android.os.Build
import android.os.StrictMode
import android.os.Trace
import timber.log.Timber
Performance optimization and profiling
kotlin
android
performance
by Alex Chen
2 tabs
kotlin
package com.example.myapp.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
App widgets for home screen
kotlin
android
widget
by Alex Chen
2 tabs
kotlin
package com.example.myapp.data.repository
import com.example.myapp.data.local.PostDao
import com.example.myapp.data.local.PostEntity
import com.example.myapp.data.remote.ApiService
import com.example.myapp.models.Post
Unit testing with JUnit and MockK
kotlin
android
testing
by Alex Chen
2 tabs
kotlin
package com.example.myapp.utils
import android.app.NotificationChannel
import android.app.NotificationChannelGroup
import android.app.NotificationManager
import android.app.PendingIntent
Notification channels and categories
kotlin
android
notifications
by Alex Chen
1 tab
Share this code
Here's the card — post it anywhere.