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

কোটলিন অ্যান্ড্রয়েড গাইড 2026: জেটপ্যাক কম্পোজ, ভিউমডেল এবং হিল্ট

⏱️3 min read  ·  631 words

কোটলিন হল অফিসিয়াল অ্যান্ড্রয়েড ডেভেলপমেন্ট ল্যাঙ্গুয়েজ এবং 2026 সালে জেটপ্যাক কম্পোজ XML লেআউটগুলিকে প্রাথমিক UI ফ্রেমওয়ার্ক হিসাবে প্রতিস্থাপন করেছে। অ্যাসিঙ্কের জন্য কোরোটিন, প্রতিক্রিয়াশীল স্ট্রিমগুলির জন্য ফ্লো এবং নির্ভরতা ইনজেকশনের জন্য হিল্ট সহ, আধুনিক অ্যান্ড্রয়েড বিকাশ আগের চেয়ে আরও বেশি উত্পাদনশীল। এই নির্দেশিকা প্রকল্প সেটআপ থেকে উত্পাদন নিদর্শন সবকিছু কভার.

প্রকল্প সেটআপ

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)

জেটপ্যাক কম্পোজ বেসিক

// 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")
        }
    }
}

স্টেটফ্লো সহ মডেল দেখুন

// 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 + Coroutines

// 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))
    }
}

রুম ডাটাবেস

// 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
@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() })
        }
    }
}

জেটপ্যাক কম্পোজ, ভিউমডেল + স্টেটফ্লো, ডিআই-এর জন্য হিল্ট, স্থানীয় স্টোরেজের জন্য রুম এবং নেটওয়ার্কিংয়ের জন্য রেট্রোফিট সহ 2026 সালে কোটলিন অ্যান্ড্রয়েড বিকাশ একটি পরিপক্ক, উত্পাদনশীল স্ট্যাক। আর্কিটেকচারটি পরিষ্কার এবং পরীক্ষাযোগ্য — প্রতিটি স্তর কোরোটিন-সচেতন পরীক্ষার ইউটিলিটিগুলির সাথে স্বাধীনভাবে পরীক্ষাযোগ্য।

✍️ Leave a Comment

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

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