Skip to content

Instantly share code, notes, and snippets.

@Matikano
Last active May 12, 2025 10:56
Show Gist options
  • Save Matikano/8f87702cafdf1eda2b53383457439b01 to your computer and use it in GitHub Desktop.
Save Matikano/8f87702cafdf1eda2b53383457439b01 to your computer and use it in GitHub Desktop.
File Templates for Android Kotlin
1. Main one - ViewModel
NAME: MVI Fragment Screen with ViewModel
FILE NAME: ${NAME}ViewModel
EXTENSION: kt
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME} #end
import ${PACKAGE_NAME}.${NAME}Action
import ${PACKAGE_NAME}.${NAME}State
import javax.inject.Inject
import dagger.hilt.android.lifecycle.HiltViewModel
@HiltViewModel
class ${NAME}ViewModel @Inject constructor(
//TODO: add ViewModel dependencies here (use cases/repositories)
): BaseViewModel<State, Action>(
initialState = State()
) {
override fun loadData() {
//TODO: initialize your data here or do nothing if not needed
}
override fun onAction(action: Action) {
when (action) {
//TODO: handle you UI Actions here
else -> Unit
}
}
}
2. Fragment
FILE NAME: ${NAME}Fragment
EXTENSION: kt
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME} #end
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import ${PACKAGE_NAME}.${NAME}ViewModel
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class ${NAME}Fragment: Fragment() {
private val viewModel: ${NAME}ViewModel by viewModels()
private var _binding: Fragment${NAME}Binding? = null
private val binding
get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = Fragment${NAME}Binding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
observeUiState()
}
private fun observeUiState() {
launchWithLifecycle {
//TODO: add observation of uiState changes here
// NOTE: observe ONLY the values that matters for particular ui components and use
// distinctUntilChanged() if you need to react to changes of values
/*
Example:
viewModel.uiState
.map { it.isLoading }
.distinctUntilChanged()
.collect { isLoading ->
binding.progressIndicator.isVisible = isLoading
}
*/
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
3. State
FILE NAME: ${NAME}State
EXTENSION: kt
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME} #end
data class ${NAME}State(
// this is stub value, remove if not needed
val isLoading: Boolean = true,
//TODO: Implement your State data here
)
4. Action
FILE NAME: ${NAME}Action
EXTENSION: kt
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME} #end
sealed interface ${NAME}Action: UiAction {
//TODO: Implement screen UiActions here (user actions)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment