前言 Android开发作为移动应用开发的核心领域,经历了从Java到Kotlin、从XML布局到Jetpack Compose的巨大变革。2025年的Android开发已经进入了全新的时代,本学习路线将带你从入门到高级架构师,掌握最新的技术栈和最佳实践。
一、Android开发基础阶段 (一)开发环境搭建 1.1 开发工具安装
1.2 第一个Android应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class MainActivity : ComponentActivity () { override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContent { MyApplicationTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting("Android" ) } } } } } @Composable fun Greeting (name: String , modifier: Modifier = Modifier) { Text( text = "Hello $name !" , modifier = modifier ) }
(二)Kotlin语言基础 2.1 Kotlin核心语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 data class User ( val id: Int , val name: String, val email: String ) fun String.isEmailValid () : Boolean { return android.util.Patterns.EMAIL_ADDRESS.matcher(this ).matches() } suspend fun fetchUserData () : List<User> { return withContext(Dispatchers.IO) { delay(1000 ) listOf( User(1 , "张三" , "zhangsan@example.com" ), User(2 , "李四" , "lisi@example.com" ) ) } }
2.2 Kotlin高阶函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 val numbers = listOf(1 , 2 , 3 , 4 , 5 )val doubled = numbers.map { it * 2 }val sum = numbers.reduce { acc, i -> acc + i }class AlertDialogBuilder { var title: String = "" var message: String = "" var positiveButton: String = "" var onPositiveClick: () -> Unit = {} fun build () : AlertDialog { return AlertDialog.Builder(context) .setTitle(title) .setMessage(message) .setPositiveButton(positiveButton) { _, _ -> onPositiveClick() } .create() } }
(三)Android核心组件 3.1 Activity与Fragment 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class MainActivity : ComponentActivity () { private val viewModel: MainViewModel by viewModels() override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) setContent { MyAppTheme { val navController = rememberNavController() NavHost( navController = navController, startDestination = "home" ) { composable("home" ) { HomeScreen(navController) } composable("detail/{id}" ) { backStackEntry -> val id = backStackEntry.arguments?.getString("id" ) DetailScreen(id, navController) } } } } } } class UserFragment : Fragment () { private val viewModel: UserViewModel by viewModels() override fun onCreateView ( inflater: LayoutInflater , container: ViewGroup ?, savedInstanceState: Bundle ? ) : View { return ComposeView(requireContext()).apply { setContent { UserScreen(viewModel) } } } }
3.2 数据存储 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @Entity(tableName = "users" ) data class UserEntity ( @PrimaryKey val id: Int , val name: String, val email: String, val createdAt: Long = System.currentTimeMillis() ) @Dao interface UserDao { @Query("SELECT * FROM users WHERE id = :id" ) suspend fun getUserById (id: Int ) : UserEntity? @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUser (user: UserEntity ) @Query("SELECT * FROM users ORDER BY createdAt DESC" ) fun getAllUsers () : Flow<List<UserEntity>> } @Database(entities = [UserEntity::class], version = 1) abstract class AppDatabase : RoomDatabase () { abstract fun userDao () : UserDao } class UserPreferences (private val dataStore: DataStore<Preferences>) { private val USER_NAME = stringPreferencesKey("user_name" ) private val IS_FIRST_LAUNCH = booleanPreferencesKey("is_first_launch" ) val userName: Flow<String> = dataStore.data .map { preferences -> preferences[USER_NAME] ?: "" } suspend fun saveUserName (name: String ) { dataStore.edit { preferences -> preferences[USER_NAME] = name } } }
二、UI开发进阶 (一)Jetpack Compose全面掌握 1.1 Compose基础组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 @Composable fun CounterScreen () { var count by remember { mutableStateOf(0 ) } Column( modifier = Modifier .fillMaxSize() .padding(16. dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = "Count: $count " , style = MaterialTheme.typography.headlineMedium ) Spacer(modifier = Modifier.height(16. dp)) Button(onClick = { count++ }) { Text("Increment" ) } } } @Composable fun UserList (users: List <User >) { LazyColumn( modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues(16. dp), verticalArrangement = Arrangement.spacedBy(8. dp) ) { items(users) { user -> UserCard(user = user) } } } @Composable fun UserCard (user: User ) { Card( modifier = Modifier.fillMaxWidth(), elevation = CardDefaults.cardElevation(defaultElevation = 4. dp) ) { Row( modifier = Modifier .fillMaxWidth() .padding(16. dp), verticalAlignment = Alignment.CenterVertically ) { AsyncImage( model = user.avatarUrl, contentDescription = "User avatar" , modifier = Modifier .size(48. dp) .clip(CircleShape) ) Spacer(modifier = Modifier.width(16. dp)) Column { Text( text = user.name, style = MaterialTheme.typography.titleMedium ) Text( text = user.email, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) } } } }
1.2 Compose动画与过渡 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 @Composable fun AnimatedVisibilityExample () { var visible by remember { mutableStateOf(true ) } Column { Button(onClick = { visible = !visible }) { Text("Toggle Visibility" ) } AnimatedVisibility( visible = visible, enter = fadeIn() + slideInVertically(), exit = fadeOut() + slideOutVertically() ) { Card( modifier = Modifier .fillMaxWidth() .padding(16. dp) ) { Text( "Animated Content" , modifier = Modifier.padding(16. dp) ) } } } } @Composable fun LoadingAnimation () { val infiniteTransition = rememberInfiniteTransition() val rotation by infiniteTransition.animateFloat( initialValue = 0f , targetValue = 360f , animationSpec = infiniteRepeatable( animation = tween(1000 , easing = LinearEasing), repeatMode = RepeatMode.Restart ) ) Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { CircularProgressIndicator( modifier = Modifier.rotate(rotation) ) } }
(二)Material Design 3 2.1 主题和样式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 private val DarkColorScheme = darkColorScheme( primary = Purple80, secondary = PurpleGrey80, tertiary = Pink80 ) private val LightColorScheme = lightColorScheme( primary = Purple40, secondary = PurpleGrey40, tertiary = Pink40 ) @Composable fun MyAppTheme ( darkTheme: Boolean = isSystemInDarkTheme() , content: @Composable () -> Unit ) { val colorScheme = when { darkTheme -> DarkColorScheme else -> LightColorScheme } MaterialTheme( colorScheme = colorScheme, typography = Typography, content = content ) } @Composable fun DynamicTheme ( darkTheme: Boolean = isSystemInDarkTheme() , content: @Composable () -> Unit ) { val context = LocalContext.current val colorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) } else { if (darkTheme) DarkColorScheme else LightColorScheme } MaterialTheme( colorScheme = colorScheme, typography = Typography, content = content ) }
三、架构设计模式 (一)MVVM架构 1.1 ViewModel实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 abstract class BaseViewModel : ViewModel () { protected val _uiState = MutableStateFlow(UiState()) val uiState: StateFlow<UiState> = _uiState.asStateFlow() protected val _event = MutableSharedFlow<Event>() val event: SharedFlow<Event> = _event.asSharedFlow() protected fun launch ( onError: (Throwable ) -> Unit = {}, onSuccess: suspend () -> Unit ) { viewModelScope.launch { try { onSuccess() } catch (e: Exception) { onError(e) _event.emit(Event.Error(e.message ?: "Unknown error" )) } } } } class UserViewModel ( private val userRepository: UserRepository, private val savedStateHandle: SavedStateHandle ) : BaseViewModel() { private val userId: String = savedStateHandle["userId" ] ?: "" init { loadUser() } private fun loadUser () { launch( onError = { error -> _uiState.update { it.copy(isLoading = false , error = error.message) } } ) { _uiState.update { it.copy(isLoading = true ) } val user = userRepository.getUser(userId) _uiState.update { it.copy(isLoading = false , user = user) } } } fun updateUser (user: User ) { launch { userRepository.updateUser(user) _event.emit(Event.UserUpdated) } } } data class UiState ( val isLoading: Boolean = false , val user: User? = null , val error: String? = null ) sealed class Event { data class Error (val message: String) : Event() object UserUpdated : Event() }
(二)Clean Architecture 2.1 分层架构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 app/ ├── presentation/ │ ├── ui/ │ │ ├── screens/ │ │ ├── components/ │ │ └── theme/ │ └── viewmodel/ ├── domain/ │ ├── model/ │ ├── repository/ │ └── usecase/ └── data/ ├── local/ ├── remote/ └── repository/
2.2 领域层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 data class User ( val id: String, val name: String, val email: String, val avatarUrl: String? ) interface UserRepository { suspend fun getUser (id: String ) : Result<User> suspend fun getUsers () : Result<List<User>> suspend fun updateUser (user: User ) : Result<Unit > suspend fun deleteUser (id: String ) : Result<Unit > } class GetUserUseCase ( private val userRepository: UserRepository ) { suspend operator fun invoke (id: String ) : Result<User> { return userRepository.getUser(id) } } class GetUsersUseCase ( private val userRepository: UserRepository ) { suspend operator fun invoke () : Result<List<User>> { return userRepository.getUsers() } }
2.3 数据层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class UserRemoteDataSource ( private val apiService: UserApiService ) { suspend fun getUser (id: String ) : UserDto { return apiService.getUser(id) } suspend fun getUsers () : List<UserDto> { return apiService.getUsers() } } class UserLocalDataSource ( private val userDao: UserDao ) { suspend fun getUser (id: String ) : UserEntity? { return userDao.getUserById(id) } suspend fun saveUsers (users: List <UserEntity >) { userDao.insertUsers(users) } } class UserRepositoryImpl ( private val remoteDataSource: UserRemoteDataSource, private val localDataSource: UserLocalDataSource, private val networkManager: NetworkManager ) : UserRepository { override suspend fun getUser (id: String ) : Result<User> { return try { if (networkManager.isConnected()) { val userDto = remoteDataSource.getUser(id) val user = userDto.toDomain() localDataSource.saveUser(user.toEntity()) Result.success(user) } else { val userEntity = localDataSource.getUser(id) userEntity?.toDomain()?.let { Result.success(it) } ?: Result.failure(Exception("User not found" )) } } catch (e: Exception) { Result.failure(e) } } }
四、网络与数据层 (一)网络通信 1.1 Retrofit + OkHttp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 interface UserApiService { @GET("users/{id}" ) suspend fun getUser (@Path("id" ) id: String ) : UserDto @GET("users" ) suspend fun getUsers ( @Query("page" ) page: Int , @Query("limit" ) limit: Int ) : List<UserDto> @POST("users" ) suspend fun createUser (@Body user: CreateUserRequest ) : UserDto @PUT("users/{id}" ) suspend fun updateUser ( @Path("id" ) id: String , @Body user: UpdateUserRequest ) : UserDto @DELETE("users/{id}" ) suspend fun deleteUser (@Path("id" ) id: String ) } object NetworkModule { private const val BASE_URL = "https://api.example.com/" private val okHttpClient = OkHttpClient.Builder() .connectTimeout(30 , TimeUnit.SECONDS) .readTimeout(30 , TimeUnit.SECONDS) .writeTimeout(30 , TimeUnit.SECONDS) .addInterceptor(AuthInterceptor()) .addInterceptor(LoggingInterceptor()) .build() private val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build() val userApiService: UserApiService = retrofit.create(UserApiService::class .java) } class AuthInterceptor : Interceptor { override fun intercept (chain: Interceptor .Chain ) : Response { val originalRequest = chain.request() val authenticatedRequest = originalRequest.newBuilder() .header("Authorization" , "Bearer ${TokenManager.getToken()} " ) .build() return chain.proceed(authenticatedRequest) } }
(二)数据持久化 2.1 Room数据库高级用法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 @Dao interface UserDao { @Query(""" SELECT * FROM users WHERE name LIKE '%' || :query || '%' OR email LIKE '%' || :query || '%' ORDER BY createdAt DESC """ ) fun searchUsers (query: String ) : Flow<List<UserEntity>> @Query(""" SELECT * FROM users WHERE createdAt BETWEEN :startDate AND :endDate ORDER BY createdAt DESC LIMIT :limit OFFSET :offset """ ) suspend fun getUsersByDateRange ( startDate: Long , endDate: Long , limit: Int , offset: Int ) : List<UserEntity> @Transaction suspend fun insertUserWithPosts (user: UserEntity , posts: List <PostEntity >) { insertUser(user) insertPosts(posts) } } @Database( entities = [UserEntity::class, PostEntity::class], version = 2, exportSchema = true, autoMigrations = [ AutoMigration(from = 1, to = 2) ] ) abstract class AppDatabase : RoomDatabase () { abstract fun userDao () : UserDao abstract fun postDao () : PostDao companion object { val MIGRATION_1_2 = object : Migration(1 , 2 ) { override fun migrate (database: SupportSQLiteDatabase ) { database.execSQL(""" ALTER TABLE users ADD COLUMN lastLoginAt INTEGER DEFAULT 0 """ ) } } } }
五、性能优化 (一)内存优化 1.1 内存泄漏检测 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class MyApplication : Application () { override fun onCreate () { super .onCreate() if (LeakCanary.isInAnalyzerProcess(this )) { return } LeakCanary.install(this ) } } object MemoryProfiler { fun logMemoryUsage (tag: String ) { val runtime = Runtime.getRuntime() val usedMemory = runtime.totalMemory() - runtime.freeMemory() val maxMemory = runtime.maxMemory() val availableMemory = maxMemory - usedMemory Log.d(tag, "Used: ${usedMemory / 1024 / 1024 } MB" ) Log.d(tag, "Available: ${availableMemory / 1024 / 1024 } MB" ) } }
1.2 图片加载优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class ImageLoaderModule { companion object { fun provideImageLoader (context: Context ) : ImageLoader { return ImageLoader.Builder(context) .memoryCache { MemoryCache.Builder(context) .maxSizePercent(0.25 ) .build() } .diskCache { DiskCache.Builder() .directory(context.cacheDir.resolve("image_cache" )) .maxSizeBytes(50 * 1024 * 1024 ) .build() } .crossfade(true ) .build() } } } object ImageCompressor { fun compressImage ( context: Context , uri: Uri , maxWidth: Int = 1080 , maxHeight: Int = 1920 , quality: Int = 80 ) : File { val bitmap = BitmapFactory.decodeStream( context.contentResolver.openInputStream(uri) ) val scaledBitmap = Bitmap.createScaledBitmap( bitmap, maxWidth, maxHeight, true ) val outputFile = File(context.cacheDir, "compressed_${System.currentTimeMillis()} .jpg" ) FileOutputStream(outputFile).use { out -> scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, out ) } return outputFile } }
(二)网络优化 2.1 网络缓存策略 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 object CacheConfig { private const val CACHE_SIZE = 10 * 1024 * 1024L fun provideCache (context: Context ) : Cache { return Cache(context.cacheDir, CACHE_SIZE) } fun provideCacheInterceptor () : Interceptor { return Interceptor { chain -> val response = chain.proceed(chain.request()) val cacheControl = CacheControl.Builder() .maxAge(1 , TimeUnit.HOURS) .build() response.newBuilder() .header("Cache-Control" , cacheControl.toString()) .build() } } }
六、测试与调试 (一)单元测试 1.1 ViewModel测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @RunWith(MockitoJUnitRunner::class) class UserViewModelTest { @Mock private lateinit var userRepository: UserRepository private lateinit var viewModel: UserViewModel @Before fun setup () { viewModel = UserViewModel(userRepository) } @Test fun `getUser should update UI state with user data `() = runTest { val userId = "123" val user = User(userId, "Test User" , "test@example.com" ) whenever(userRepository.getUser(userId)).thenReturn(Result.success(user)) viewModel.loadUser(userId) viewModel.uiState.test { val state = awaitItem() assertEquals(false , state.isLoading) assertEquals(user, state.user) } } }
(二)UI测试 2.1 Compose UI测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class UserScreenTest { @get:Rule val composeTestRule = createComposeRule() @Test fun userList_displaysCorrectly () { val users = listOf( User("1" , "Alice" , "alice@example.com" ), User("2" , "Bob" , "bob@example.com" ) ) composeTestRule.setContent { UserList(users = users) } composeTestRule.onNodeWithText("Alice" ).assertIsDisplayed() composeTestRule.onNodeWithText("Bob" ).assertIsDisplayed() } @Test fun userCard_clickAction () { var clickedUser: User? = null val user = User("1" , "Alice" , "alice@example.com" ) composeTestRule.setContent { UserCard( user = user, onUserClick = { clickedUser = it } ) } composeTestRule.onNodeWithText("Alice" ).performClick() assertEquals(user, clickedUser) } }
七、高级架构与组件化 (一)模块化架构 1.1 模块划分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 app/ ├── app/ │ ├── src/main/java/com/example/app/ │ │ ├── MainActivity.kt │ │ └── MyApplication.kt ├── core/ │ ├── data/ │ ├── domain/ │ └── ui/ ├── features/ │ ├── home/ │ ├── profile/ │ └── settings/ └── libraries/ ├── network/ ├── database/ └── common/
1.2 动态功能模块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 plugins { id 'com.android.dynamic-feature' id 'kotlin-android' } android { compileSdk 34 defaultConfig { minSdk 21 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } } dependencies { implementation project (':app' ) implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material3:material3:$compose_version" }
(二)依赖注入 2.1 Hilt集成 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 @HiltAndroidApp class MyApplication : Application ()@Module @InstallIn(SingletonComponent::class) object AppModule { @Provides @Singleton fun provideDatabase (@ApplicationContext context: Context ) : AppDatabase { return Room.databaseBuilder( context, AppDatabase::class .java, "app_database" ).build() } @Provides @Singleton fun provideUserRepository ( userDao: UserDao , userApiService: UserApiService ) : UserRepository { return UserRepositoryImpl(userDao, userApiService) } } @HiltViewModel class UserViewModel @Inject constructor ( private val getUserUseCase: GetUserUseCase, private val savedStateHandle: SavedStateHandle ) : ViewModel() { }
八、现代Android开发 (一)Jetpack Compose高级特性 1.1 动画系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 @Composable fun AnimatedCard ( isExpanded: Boolean , onToggle: () -> Unit ) { val transition = updateTransition( targetState = isExpanded, label = "card_transition" ) val cardElevation by transition.animateDp( label = "elevation" ) { expanded -> if (expanded) 8. dp else 2. dp } val cardCornerRadius by transition.animateDp( label = "corner_radius" ) { expanded -> if (expanded) 16. dp else 8. dp } Card( elevation = CardDefaults.cardElevation(defaultElevation = cardElevation), shape = RoundedCornerShape(cardCornerRadius), modifier = Modifier .fillMaxWidth() .clickable { onToggle() } ) { } } @Composable fun SharedElementTransition ( isVisible: Boolean , sharedTransitionScope: SharedTransitionScope , animatedVisibilityScope: AnimatedVisibilityScope ) { with(sharedTransitionScope) { Card( modifier = Modifier .sharedBounds( rememberSharedContentState(key = "card" ), animatedVisibilityScope ) ) { } } }
(二)现代架构组件 2.1 Navigation Compose 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Composable fun AppNavigation () { val navController = rememberNavController() NavHost( navController = navController, startDestination = "home" ) { composable("home" ) { HomeScreen( onUserClick = { userId -> navController.navigate("user/$userId " ) } ) } composable( "user/{userId}" , arguments = listOf(navArgument("userId" ) { type = NavType.StringType }) ) { backStackEntry -> val userId = backStackEntry.arguments?.getString("userId" ) UserDetailScreen( userId = userId, onBackClick = { navController.popBackStack() } ) } composable( "user/{userId}" , deepLinks = listOf( navDeepLink { uriPattern = "https://example.com/user/{userId}" } ) ) { backStackEntry -> } } }
九、性能监控与优化 (一)性能分析工具 1.1 Android Profiler使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class PerformanceMonitor { companion object { fun startMethodTracing (traceName: String ) { Debug.startMethodTracing(traceName) } fun stopMethodTracing () { Debug.stopMethodTracing() } fun measureTime (block: () -> Unit ) : Long { val startTime = System.currentTimeMillis() block() return System.currentTimeMillis() - startTime } } }
(二)崩溃分析 2.1 Firebase Crashlytics 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class CrashReportingTree : Timber.Tree () { override fun log (priority: Int , tag: String ?, message: String , t: Throwable ?) { if (priority == Log.ERROR || priority == Log.WARN) { FirebaseCrashlytics.getInstance().log(message) t?.let { FirebaseCrashlytics.getInstance().recordException(it) } } } } class CustomExceptionHandler : Thread.UncaughtExceptionHandler { private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler() override fun uncaughtException (thread: Thread , throwable: Throwable ) { saveCrashInfo(throwable) uploadCrashReport(throwable) defaultHandler?.uncaughtException(thread, throwable) } }
十、发布与持续集成 (一)CI/CD配置 1.1 GitHub Actions 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 name: Android CI on: push: branches: [ main , develop ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' - name: Cache Gradle packages uses: actions/cache@v3 with: path: | ~/.gradle/caches ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties' ) }} - name: Run tests run: ./gradlew test - name: Build APK run: ./gradlew assembleDebug - name: Upload APK uses: actions/upload-artifact@v3 with: name: app-debug path: app/build/outputs/apk/debug/app-debug.apk
(二)应用签名与发布 2.1 签名配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 android { signingConfigs { release { storeFile file ("keystore/release.keystore" ) storePassword System.getenv("KEYSTORE_PASSWORD" ) keyAlias System.getenv("KEY_ALIAS" ) keyPassword System.getenv("KEY_PASSWORD" ) } } buildTypes { release { signingConfig signingConfigs.release minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt' ), 'proguard-rules.pro' } } }
十一、学习资源与路线图 (一)官方资源
(二)推荐书籍
《Android编程权威指南》
《Kotlin实战》
《Clean Architecture》
《Android高级编程》
(三)在线课程
(四)实践项目建议 阶段1:基础项目(1-2个月)
天气应用:使用OpenWeatherMap API
待办事项应用:Room数据库 + Compose
新闻阅读器:Retrofit + RecyclerView
阶段2:进阶项目(2-3个月)
社交媒体客户端:完整用户系统
电商应用:购物车 + 支付集成
音乐播放器:媒体播放 + 通知
阶段3:高级项目(3-4个月)
即时通讯应用:WebSocket + 推送通知
地图导航应用:Google Maps + 定位
视频流媒体应用:ExoPlayer + 缓存
十二、2025年Android开发趋势 (一)新技术方向
AI集成 : 机器学习模型在移动端的部署
跨平台 : Kotlin Multiplatform Mobile (KMM)
可穿戴设备 : Wear OS 4.0开发
大屏适配 : 折叠屏和平板优化
性能优化 : 启动速度和应用体积优化
(二)架构演进
响应式架构 : 基于Flow的响应式编程
微前端 : 模块化架构的进一步发展
Server-Driven UI : 服务端驱动UI更新
边缘计算 : 本地AI处理能力增强
总结 Android开发在2025年已经进入了全新的时代,从传统的Java + XML开发模式,演进到了Kotlin + Compose的现代化开发。本学习路线涵盖了从基础到高级的完整知识体系,包括最新的架构模式、性能优化、测试策略和发布流程。
掌握这些技能将使你能够开发出高质量、高性能的Android应用,并为成为高级Android架构师打下坚实基础。记住,持续学习和实践是成为优秀Android开发者的关键。