Lewati ke konten utama

Android — Kotlin

Standar pengembangan aplikasi Android menggunakan Kotlin sebagai bahasa utama.

Tech Stack​

KategoriLibrary / ToolVersi Min.
LanguageKotlin2.4+ (K2 compiler)
Min SDKAPI 24 (Android 7.0)—
Target SDKAPI 36 (Android 16)Wajib untuk app baru per 31 Agu 2026
Build SystemGradle (Kotlin DSL)9.x
UIJetpack ComposeLatest (via Compose BOM)
NavigationCompose NavigationLatest
DIHilt / KoinLatest
NetworkingRetrofit + OkHttp3.x + 5.x
SerializationKotlinx SerializationLatest
Image LoadingCoil3.x (io.coil-kt.coil3, Kotlin Multiplatform)
Local DBRoomLatest
State ManagementViewModel + StateFlow—
TestingJUnit 5, MockK, Turbine—
CI/CDFastlane + GitLab CI—

Project Structure​

app/
├── src/
│ ├── main/
│ │ ├── java/com/bitgroup/appname/
│ │ │ ├── data/ # Data layer
│ │ │ │ ├── remote/ # API services & DTOs
│ │ │ │ ├── local/ # Room DAOs & entities
│ │ │ │ └── repository/ # Repository implementations
│ │ │ ├── domain/ # Domain layer
│ │ │ │ ├── model/ # Domain models
│ │ │ │ ├── repository/ # Repository interfaces
│ │ │ │ └── usecase/ # Use cases
│ │ │ ├── presentation/ # Presentation layer
│ │ │ │ ├── ui/ # Composable screens
│ │ │ │ ├── viewmodel/ # ViewModels
│ │ │ │ └── navigation/ # Nav graph
│ │ │ ├── di/ # Hilt modules
│ │ │ └── core/ # Utilities, extensions
│ │ └── res/
│ └── test/ # Unit tests
│ └── androidTest/ # Instrumented tests
├── build.gradle.kts
└── gradle/
└── libs.versions.toml # Version catalog

Coding Standards​

Kotlin Style Guide​

Jetpack Compose Best Practices​

// ✅ Good - Stateless composable
@Composable
fun UserCard(
user: UserUiModel,
onTap: () -> Unit,
modifier: Modifier = Modifier,
) {
Card(
modifier = modifier.clickable(onClick = onTap),
) {
Text(text = user.name)
}
}

// ❌ Bad - Business logic inside composable
@Composable
fun UserCard(userId: String) {
val user = repository.getUser(userId) // Jangan!
Text(text = user.name)
}

ViewModel Pattern​

@HiltViewModel
class UserViewModel @Inject constructor(
private val getUserUseCase: GetUserUseCase,
) : ViewModel() {

private val _uiState = MutableStateFlow<UserUiState>(UserUiState.Loading)
val uiState: StateFlow<UserUiState> = _uiState.asStateFlow()

fun loadUser(id: String) {
viewModelScope.launch {
_uiState.value = UserUiState.Loading
getUserUseCase(id)
.onSuccess { _uiState.value = UserUiState.Success(it) }
.onFailure { _uiState.value = UserUiState.Error(it.message) }
}
}
}

sealed interface UserUiState {
data object Loading : UserUiState
data class Success(val user: User) : UserUiState
data class Error(val message: String?) : UserUiState
}

Build & Run​

# Debug build
./gradlew assembleDebug

# Run unit tests
./gradlew test

# Run lint
./gradlew ktlintCheck

# Generate signed APK
./gradlew assembleRelease
Version Catalog

Semua dependency version harus didefinisikan di gradle/libs.versions.toml untuk konsistensi multi-module project.