Android代码架构

Android代码架构通常包括四个主要层次:应用层、框架层、原生层和Linux内核层。下面我们用mermaid图来表示:

graph TD A[应用层] --> B[框架层] B --> C1[原生层] C1 --> C2[原生层中的Android运行时] C2 --> D[Linux内核层] subgraph A[应用层] A1[系统应用] A2[第三方应用] end subgraph B[框架层] B1[Activity Manager] B2[Window Manager] B3[Content Providers] B4[View System] B5[Notification Manager] B6[Package Manager] B7[Telephony Manager] B8[Resource Manager] B9[Location Manager] B10[XMPP Service] end subgraph C1[原生层] C1A[原生C/C++库] C1B[Android运行时] end subgraph C2[原生层中的Android运行时] C2A[Dalvik虚拟机] C2B[ART] end subgraph D[Linux内核层] D1[显示驱动] D2[摄像头驱动] D3[蓝牙驱动] D4[USB驱动] D5[键区驱动] D6[WiFi驱动] D7[音频驱动] D8[电源管理] end

结合这个图示来详细阐述Android代码架构:

  1. 应用层(Application Layer)

    • 这是用户直接接触的层面,包括系统自带的应用程序(如联系人、短信、相机等)和第三方应用程序(如微信、淘宝等)。
    • 应用层使用Java或Kotlin语言编写,运行在Android运行时(ART)上。
  2. 框架层(Framework Layer)

    • 框架层为应用层提供了大量的API,使开发者能够快速开发应用程序。框架层包含了各种管理器和服务,例如:

      • Activity Manager:管理应用程序的生命周期和活动栈。
      • Window Manager:管理窗口程序。
      • Content Providers:管理应用程序间数据共享。
      • View System:构建用户界面的基本组件。
      • Notification Manager:管理通知。
      • Package Manager:管理应用程序包。
      • Telephony Manager:管理移动设备功能。
      • Resource Manager:管理非代码资源(如图片、字符串等)。
      • Location Manager:管理位置服务。
      • XMPP Service:管理即时通讯服务。
    • 框架层主要使用Java语言编写。

  3. 原生层(Native Layer)

    • 原生层包括原生C/C++库和Android运行时。
    • 原生C/C++库:包括一系列C/C++库,如OpenGL ES、Webkit、SQLite等,这些库为Android系统提供了底层的功能支持。
    • Android运行时:包括Dalvik虚拟机和ART。从Android 5.0开始,ART取代了Dalvik虚拟机。ART在应用安装时将字节码转换为机器码,提高了应用的运行效率。
    • 原生层还包含了硬件抽象层(HAL),它提供了标准接口,使得框架层能够与硬件设备进行通信,而无需关心底层驱动实现。
  4. Linux内核层(Linux Kernel Layer)

    • Android基于Linux内核,但增加了一些特定的驱动和功能,如电源管理、进程管理等。
    • 该层包含了各种硬件驱动,如显示驱动、摄像头驱动、蓝牙驱动、USB驱动、键区驱动、WiFi驱动、音频驱动等。
    • Linux内核层还负责系统安全、内存管理、进程管理、网络协议栈等。

除了上述层次,Android架构中还包含了一些重要的组件和概念,如:

  • 四大组件:Activity、Service、BroadcastReceiver、ContentProvider。
  • Intent:用于在组件之间传递消息。
  • Binder:Android中的一种跨进程通信(IPC)机制。
  • Handler:用于线程间通信,特别是在主线程(UI线程)和子线程之间。
  • View和ViewGroup:构建用户界面的基础。
  • 资源管理:如何管理图片、字符串、布局等资源。
  • 清单文件(AndroidManifest.xml) :声明组件、权限等。

一、Android代码架构演进与核心思想

Android应用架构的核心思想是分离关注点数据驱动UI。架构的演进是为了让代码更易于测试、维护和团队协作。

  1. MVC:早期模式,但在Android中,Activity/Fragment经常承担了Controller和View的双重角色,导致它们过于臃肿。
  2. MVP:引入了Presenter层,将UI逻辑从Activity/Fragment中抽离出来,大大改善了可测试性。
  3. MVVM :当前主流和官方推荐 的架构。它利用数据绑定生命周期感知组件,实现了数据与UI的自动同步,进一步减少了模板代码。

二、现代Android应用架构详解

下面我们以MVVM为核心,结合Jetpack组件,来剖析一个完整的、现代的Android应用架构。

graph TD subgraph UI Layer A[Activity/Fragment] --> B[ViewModel]; B --> A; A --> C[Composable - 可选]; end subgraph Domain Layer - 可选 D[Use Case] --> E[Repository Interface]; end subgraph Data Layer F[Repository] --> G[Local Data Source]; F --> H[Remote Data Source]; subgraph G[Local Data Source] G1[Room Database] end subgraph H[Remote Data Source] H1[Retrofit Service] end end B --> D; D --> F; F --> B; style UI Layer fill:#cde4ff style Domain Layer fill:#ffeccd style Data Layer fill:#d4ffcd

三个核心层以及它们之间的依赖关系:UI层 -> 领域层 -> 数据层。数据流是单向的。

三、各层核心技术详解与代码示例

1. UI层

职责:在屏幕上显示应用数据,并处理用户交互。

核心技术

  • Activity / Fragment:UI的容器,负责处理系统交互和生命周期。
  • Jetpack Compose现代首选的声明式UI工具包,用Kotlin代码构建界面。
  • View System:传统的基于XML的UI系统。
  • ViewModel架构核心,为UI准备和管理数据。它能在配置变更(如屏幕旋转)后存活。
  • LiveData / StateFlow :可观察的数据持有者。StateFlow是Kotlin协程中的现代选择,与Compose配合极佳。
  • DataBinding / ViewBinding:用于将UI组件与数据源绑定。

代码示例 (Compose + ViewModel + StateFlow)

kotlin 复制代码
// 1. ViewModel
class MainViewModel(
    private val getPostsUseCase: GetPostsUseCase // 使用用例
) : ViewModel() {

    // UI状态使用 StateFlow 暴露
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    init {
        loadPosts()
    }

    private fun loadPosts() {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            try {
                val posts = getPostsUseCase()
                _uiState.value = UiState.Success(posts)
            } catch (e: Exception) {
                _uiState.value = UiState.Error(e.message ?: "Unknown error")
            }
        }
    }
}

// 密封类(Sealed Class)用来表示所有可能的UI状态
sealed class UiState {
    object Loading : UiState()
    data class Success(val posts: List<Post>) : UiState()
    data class Error(val message: String) : UiState()
}

// 2. Composable UI
@Composable
fun MainScreen(
    viewModel: MainViewModel = hiltViewModel() // 使用Hilt依赖注入获取ViewModel
) {
    val uiState by viewModel.uiState.collectAsState()

    when (val state = uiState) {
        is UiState.Loading -> {
            CircularProgressIndicator()
        }
        is UiState.Success -> {
            LazyColumn {
                items(state.posts) { post ->
                    PostItem(post = post)
                }
            }
        }
        is UiState.Error -> {
            Text(text = "Error: ${state.message}", color = Color.Red)
        }
    }
}

@Composable
fun PostItem(post: Post) {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp)
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = post.title, fontWeight = FontWeight.Bold)
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = post.body)
        }
    }
}

2. 领域层

职责 :封装复杂的业务逻辑,或组合多个Repository的调用。它是一个可选层,但对于复杂业务逻辑非常有用,可以使代码更清晰、可复用。

核心技术

  • Use Cases / Interactors:每个UseCase应该只负责一个单一的业务功能。

代码示例

kotlin 复制代码
// 获取帖子列表的用例
class GetPostsUseCase(
    private val postsRepository: PostsRepository
) {
    // 使用'operator invoke'可以让调用像函数一样简单:useCase()
    suspend operator fun invoke(): List<Post> {
        // 在这里可以添加业务逻辑,比如过滤、排序等
        return postsRepository.getPosts()
    }
}

// 另一个例子:刷新帖子数据的用例
class RefreshPostsUseCase(
    private val postsRepository: PostsRepository
) {
    suspend operator fun invoke() {
        postsRepository.refreshPosts()
    }
}

3. 数据层

职责:管理应用的数据,包括来自网络、本地数据库等多种数据源。它提供单一的数据入口给上层。

核心技术

  • Repository:架构核心,是数据的唯一来源。它决定从网络还是本地数据库获取数据,并处理缓存策略。
  • Room:SQLite的对象映射库,用于本地数据持久化。
  • Retrofit:类型安全的HTTP客户端,用于访问网络API。
  • WorkManager:管理后台任务。
  • Paging Library:分页加载数据。

代码示例

kotlin 复制代码
// 1. Data Class (Entity)
@Entity(tableName = "posts")
data class Post(
    @PrimaryKey val id: Int,
    val title: String,
    val body: String
)

// 2. Retrofit API Interface
interface PostsApiService {
    @GET("posts")
    suspend fun getPosts(): List<Post>
}

// 3. Room Dao (Data Access Object)
@Dao
interface PostDao {
    @Query("SELECT * FROM posts")
    fun getPosts(): Flow<List<Post>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAll(posts: List<Post>)
}

// 4. Repository 实现
class DefaultPostsRepository(
    private val apiService: PostsApiService,
    private val postDao: PostDao,
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : PostsRepository {

    // 对外暴露一个Flow,这样UI可以持续观察数据库的变化
    override fun getPosts(): Flow<List<Post>> {
        return postDao.getPosts()
    }

    // 刷新策略:网络优先,失败则使用缓存
    override suspend fun refreshPosts() {
        withContext(ioDispatcher) {
            try {
                val posts = apiService.getPosts()
                postDao.insertAll(posts)
            } catch (e: Exception) {
                // 处理网络错误,例如抛出错误状态或使用缓存
                throw e
            }
        }
    }
}

四、依赖注入 - 架构的粘合剂

为什么重要:它管理着类之间的依赖关系,使得代码更松散耦合、更易测试。

核心技术

  • Hilt官方推荐的基于Dagger的DI库,极大简化了Android上的DI配置。

代码示例

kotlin 复制代码
// 1. 使用Hilt定义依赖
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    @Singleton
    fun providePostsApiService(): PostsApiService {
        return Retrofit.Builder()
            .baseUrl("https://jsonplaceholder.typicode.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(PostsApiService::class.java)
    }

    @Provides
    @Singleton
    fun providePostDatabase(@ApplicationContext context: Context): PostDatabase {
        return Room.databaseBuilder(
            context,
            PostDatabase::class.java,
            "posts.db"
        ).build()
    }
}

@Module
@InstallIn(ViewModelComponent::class)
object UseCaseModule {
    @Provides
    fun provideGetPostsUseCase(repository: PostsRepository): GetPostsUseCase {
        return GetPostsUseCase(repository)
    }
}

// 2. 在ViewModel中使用Hilt注入
@HiltViewModel
class MainViewModel @Inject constructor(
    private val getPostsUseCase: GetPostsUseCase // Hilt自动注入
) : ViewModel() { ... }

五、如何掌握

遵循一个由浅入深、理论与实践结合的路径:

第一阶段:基础入门

  1. Kotlin语言:掌握基础语法、数据类、密封类、扩展函数、Lambda表达式。
  2. Android基础:Activity/Fragment生命周期、常用布局和控件。
  3. 构建第一个App:一个简单的静态界面App。

第二阶段:核心架构与异步编程

  1. ViewModel & LiveData/StateFlow:理解为何要使用它们,并在项目中实践。
  2. Coroutines重中之重 !理解协程的作用,掌握launch, async, flow等基本概念。
  3. Room:学习本地数据库操作。
  4. Retrofit:学习网络请求。
  5. 项目实践:构建一个简单的"待办事项"或"新闻阅读"App,使用以上所有技术,实现数据的增删改查。

第三阶段:进阶与现代化工具

  1. Jetpack Compose:开始学习声明式UI。从基础组件和状态管理入手。
  2. Hilt:在之前的项目中引入Hilt,管理所有依赖。
  3. Repository模式:重构你的"新闻阅读"App,明确分离数据层和UI层。

第四阶段:精通与最佳实践

  1. Use Cases:在更复杂的项目中引入领域层。

  2. Paging 3.0:学习列表分页。

  3. Navigation:学习应用内页面导航。

  4. Testing:为ViewModel、Repository、UseCase编写单元测试,为UI编写仪器测试。

  5. 关注官方资源

    • Android Developers官网:有最权威的指南和文档。
    • Now in Android:Google官方示例项目,展示了所有最新最佳实践。
    • Google Codelabs:提供手把手的免费教程。

总结

现代Android架构是一个围绕 MVVM分层设计单向数据流响应式编程 构建的生态系统。核心技术栈是 Kotlin + Jetpack (ViewModel, Room, Compose) + Coroutines/Flow + Hilt

从简单开始,然后逐步将学到的每一项新技术应用到项目中,不断重构和优化你的代码结构。通过实践,才能真正理解和掌握这套强大的架构。

相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone2 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui