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

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

相关推荐
ZFJ_张福杰8 小时前
【Flutter】GetX最佳实践与避坑指南
android·flutter·ios·getx
一直向钱15 小时前
android 基于okhttp的socket封装
android·okhttp
夜晚中的人海16 小时前
【C++】异常介绍
android·java·c++
蜀中廖化20 小时前
Android Studio 导入 opencv
android·opencv·android studio
奋斗的小鹰21 小时前
ASM Bytecode Viewer 插件查看kotlin和java文件的字节码
android·kotlin·asm
欢喜躲在眉梢里1 天前
mysql中的日志
android·运维·数据库·mysql·adb·日志·mysql日志
路上^_^1 天前
安卓基础组件019-引导页布局001
android·安卓
梦终剧1 天前
【Android之路】UI消息循环机制
android·ui
zh_xuan1 天前
Android android.util.LruCache源码阅读
android·源码阅读·lrucache