🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Kotlin Android Guide 2026: Jetpack Compose, ViewModel und Hilt

⏱️4 min read  ·  741 words

Kotlin ist die offizielle Android-Entwicklungssprache und im Jahr 2026 hat Jetpack Compose XML-Layouts als primäres UI-Framework abgelöst. Mit Coroutinen für Async, Flow für reaktive Streams und Hilt für die Abhängigkeitsinjektion ist die moderne Android-Entwicklung produktiver denn je. Dieser Leitfaden deckt alles ab, von der Projekteinrichtung bis hin zu Produktionsmustern.

Projekt-Setup

Android Studio Hedgehog (or newer) — recommended IDE

New project:
  Template: Empty Activity (Compose)
  Language: Kotlin
  Min SDK: 24 (Android 7.0, 96% coverage)
  Build System: Gradle with Kotlin DSL (build.gradle.kts)

Jetpack Compose-Grundlagen

// MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                // Content here
                UserListScreen()
            }
        }
    }
}

// Composable functions = UI components
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 8.dp)
            .clickable { onClick() },
        elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
    ) {
        Row(
            modifier = Modifier.padding(16.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            AsyncImage(  // Coil library
                model = user.avatarUrl,
                contentDescription = "Avatar",
                modifier = Modifier
                    .size(48.dp)
                    .clip(CircleShape)
            )
            Spacer(modifier = Modifier.width(12.dp))
            Column {
                Text(text = user.name, style = MaterialTheme.typography.titleMedium)
                Text(
                    text = user.email,
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.outline
                )
            }
        }
    }
}

// State management
@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }

    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(text = "Count: $count", style = MaterialTheme.typography.headlineMedium)
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

ViewModel mit StateFlow

// UserViewModel.kt
@HiltViewModel
class UserViewModel @Inject constructor(
    private val userRepository: UserRepository
) : ViewModel() {

    // UI state
    sealed class UiState {
        object Loading : UiState()
        data class Success(val users: List<User>) : UiState()
        data class Error(val message: String) : UiState()
    }

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

    init {
        loadUsers()
    }

    private fun loadUsers() {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            userRepository.getUsers()
                .catch { e -> _uiState.value = UiState.Error(e.message ?: "Unknown error") }
                .collect { users -> _uiState.value = UiState.Success(users) }
        }
    }

    fun createUser(name: String, email: String) {
        viewModelScope.launch {
            try {
                userRepository.createUser(User(name = name, email = email))
                loadUsers()  // refresh
            } catch (e: Exception) {
                _uiState.value = UiState.Error("Failed to create user: ${e.message}")
            }
        }
    }
}

// UserListScreen.kt
@Composable
fun UserListScreen(viewModel: UserViewModel = hiltViewModel()) {
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()

    when (val state = uiState) {
        is UserViewModel.UiState.Loading -> CircularProgressIndicator()
        is UserViewModel.UiState.Error -> ErrorMessage(state.message)
        is UserViewModel.UiState.Success -> UserList(
            users = state.users,
            onUserClick = { /* navigate */ }
        )
    }
}

Retrofit + Coroutinen

// ApiService.kt
interface ApiService {
    @GET("users")
    suspend fun getUsers(): List<UserResponse>

    @GET("users/{id}")
    suspend fun getUser(@Path("id") id: Int): UserResponse

    @POST("users")
    suspend fun createUser(@Body request: CreateUserRequest): UserResponse
}

// NetworkModule.kt (Hilt)
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun provideOkHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .addInterceptor { chain ->
                val request = chain.request().newBuilder()
                    .addHeader("Authorization", "Bearer ${BuildConfig.API_TOKEN}")
                    .build()
                chain.proceed(request)
            }
            .build()
    }

    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService =
        retrofit.create(ApiService::class.java)
}

// UserRepository.kt
class UserRepositoryImpl @Inject constructor(
    private val apiService: ApiService,
    private val userDao: UserDao  // Room local cache
) : UserRepository {

    override fun getUsers(): Flow<List<User>> = flow {
        // Emit cached data first
        userDao.getAllUsers().collect { emit(it.map(UserEntity::toDomain)) }

        // Fetch fresh data
        val freshUsers = apiService.getUsers()
        userDao.insertUsers(freshUsers.map(UserResponse::toEntity))
    }
}

Raumdatenbank

// User entity
@Entity(tableName = "users")
data class UserEntity(
    @PrimaryKey val id: Int,
    val name: String,
    val email: String,
    val createdAt: Long = System.currentTimeMillis()
)

// DAO
@Dao
interface UserDao {
    @Query("SELECT * FROM users ORDER BY createdAt DESC")
    fun getAllUsers(): Flow<List<UserEntity>>

    @Query("SELECT * FROM users WHERE id = :id")
    suspend fun getUserById(id: Int): UserEntity?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUsers(users: List<UserEntity>)

    @Delete
    suspend fun deleteUser(user: UserEntity)
}

// Database
@Database(entities = [UserEntity::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

// Hilt module
@Provides
@Singleton
fun provideDatabase(@ApplicationContext ctx: Context): AppDatabase {
    return Room.databaseBuilder(ctx, AppDatabase::class.java, "app_db").build()
}

Navigation mit Compose

// Navigation
@Composable
fun AppNavigation() {
    val navController = rememberNavController()

    NavHost(navController = navController, startDestination = "users") {
        composable("users") {
            UserListScreen(
                onUserClick = { userId -> navController.navigate("user/$userId") }
            )
        }
        composable("user/{userId}") { backStackEntry ->
            val userId = backStackEntry.arguments?.getString("userId")?.toIntOrNull()
            UserDetailScreen(userId = userId)
        }
        composable("create-user") {
            CreateUserScreen(onCreated = { navController.popBackStack() })
        }
    }
}

Die Kotlin-Android-Entwicklung im Jahr 2026 mit Jetpack Compose, ViewModel + StateFlow, Hilt für DI, Raum für lokalen Speicher und Retrofit für Netzwerke ist ein ausgereifter, produktiver Stack. Die Architektur ist sauber und testbar – jede Schicht kann unabhängig mit Coroutinen-fähigen Testdienstprogrammen getestet werden.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা