ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Android开发第一步:认识应用总体结构与工程目录

Android开发第一步:认识应用总体结构与工程目录 「Android开发1认识总体结构」——很多新手学Android第一步就摔在“不知道自己在看什么”上。打开Android Studio新建一个项目满屏的文件夹、Gradle脚本、XML文件扑面而来视频教程说“点这里、点那里”你跟着点了但完全不知道为什么要这么做。我早期带过不少新人发现一个共性凡是先花时间把Android应用的整体结构搞明白的后面学UI、学网络、学存储都快得多凡是上来就埋头敲代码的遇到问题就卡住连报错日志都看不明白。这篇文章就是带你走一遍这条“先认识结构”的路把Android应用到底是什么、工程目录里每样东西干什么用的、系统是怎么把代码变成你手机上那个App的全部摊开讲清楚。1. 从零认识Android应用应用到底是什么1.1 一个Android应用的本质界面、逻辑与数据的组合先别急着碰代码先回答一个最基础的问题你在手机上长按一个图标点进去看到一个界面然后你点按钮、滑列表、输文字这一切背后到底是什么在运转从最朴素的视角看一个Android应用就是三样东西的组合界面UI、逻辑Logic、数据Data。界面是你看得见摸得着的部分——布局、按钮、图片、文字逻辑是你操作之后发生的反应——点了“登录”按钮校验用户名密码、跳转到主页数据是应用需要读写的信息——用户资料、本地缓存、网络返回的JSON。这三者不是独立的而是互相咬合在一起界面把用户的操作交给逻辑层逻辑层处理和读写数据然后把结果再反馈回界面刷新显示。Android系统的所有框架设计本质上都在围绕这三个角色的协作来做文章。比如你写一个登录界面布局文件定义界面长什么样Activity里的Java/Kotlin代码写点击事件逻辑SharedPreferences或者数据库负责存登录状态——这就是一个最小的完整闭环。这个认识很重要因为后面你接触到的Activity、Fragment、ViewModel、Repository这些东西全都是在帮你把这三种角色分得更清楚、协作得更顺畅。带着“界面/逻辑/数据”这个框架去学你会发现Android的各种组件其实都有自己明确的“岗位”。1.2 四大组件Android应用的骨架如果说界面、逻辑、数据是应用的“血肉”那么Android的四大组件就是应用的“骨骼”。这四个组件是Android系统定义的四种标准形态任何应用的基本功能都由它们承载Activity活动负责界面展示和用户交互。一个Activity通常对应一个可交互的屏幕页面相当于App的“一扇窗口”。你的应用有几个页面通常就有几个Activity。Service服务负责后台执行耗时任务不提供界面。比如播放音乐、下载文件即使切到后台也继续跑。BroadcastReceiver广播接收器负责接收系统或应用发出的“广播信号”。比如电量低、开机完成、网络变化应用可以注册Receiver去响应这些事件。ContentProvider内容提供者负责跨应用共享数据相当于给其他App提供一个标准化的数据访问接口比如通讯录、相册都是通过ContentProvider暴露给其他App的。我见过很多新手问“四大组件有什么用我写个小App用不到吧”——话不能这么说。四大组件是Android系统的“约定”系统不知道你的Activity类叫什么名字但只要你继承Activity并按要求在清单文件里注册系统就知道怎么创建它、怎么调度它。这是Android和普通Java程序最大的区别你的代码不是自己从main函数跑起来的而是被系统“按需唤起”的。理解这一点才算真正理解Android应用的结构。1.3 为什么先学结构而不是先写代码很多入门教程第一课就是“Hello World”新建项目、改TextView文本、跑起来。我的看法恰恰相反Hello World应该放到认识结构之后再做。理由很简单如果不了解工程结构你会把“能跑起来”误解为“学会了”然后下一个需求直接把你打回原形——比如想多加一个页面不知道要建Activity、要改布局文件、要注册Manifest哪怕逻辑很简单也会手足无措。先认识结构其实是在给自己画一张“城市地图”。知道城市有哪些区目录结构、每区有什么功能各文件职责、交通怎么串联组件间的通信后面你在这个城市里办事写功能、改bug永远不会迷路。所以这一课虽然看起来“不写代码”但其实是最省时间的一课。2. 工程结构拆解Android Studio里的项目到底放了什么2.1 一个标准的Android项目长什么样打开Android Studio用Empty Activity模板新建一个项目默认会生成很多文件和目录。我先列一个最常见的工程骨架然后逐个解释每个部分是干什么的MyApplication/ ├── app/ │ ├── src/ │ │ ├── main/ │ │ │ ├── java/com/example/myapplication/ │ │ │ │ ├── MainActivity.kt │ │ │ ├── res/ │ │ │ │ ├── layout/activity_main.xml │ │ │ │ ├── values/strings.xml │ │ │ │ ├── drawable/ │ │ │ ├── AndroidManifest.xml │ ├── build.gradle ├── gradle/ ├── build.gradle ├── settings.gradle不要被这么多层目录吓到。整个项目最核心的内容就在app/src/main下面Java/Kotlin源码、资源文件、清单文件。外面那一层gradle目录和build.gradle本质上只是“构建配置”。你先抓住主线——代码、资源、清单——其他的都可以以后慢慢补。2.2 代码目录与资源目录职责分明java/或kotlin/目录存放你写的所有业务逻辑代码。注意包名结构比如com.example.myapplication这是应用的唯一标识。Android要求包名全网唯一因为系统靠它区分不同应用。你在代码里新建Activity、写工具类、做网络请求都放在这个目录里按业务分包管理。res/目录是资源文件的家里面有几个关键子目录必须搞清楚layout/布局XML文件描述界面长什么样。比如activity_main.xml里定义了LinearLayout、Button、TextView这些控件怎么摆放。values/常量和字符串资源。字符串、颜色值、尺寸都建议放在这里而不是硬编码在代码里——这是Android的强烈推荐做法方便国际化和管理。drawable/图片、Shape形状、selector选择器等图形资源。mipmap/应用图标。为什么单独一个目录因为Android需要为不同屏幕密度提供不同尺寸的图标。资源文件有一个特点编译后会自动生成R类。你在代码里写R.string.app_name实际上引用的是res/values/strings.xml里定义的那个字符串。这个机制看着绕但好处是“界面描述”和“逻辑代码”完全解耦改文案、换颜色都不用碰代码。2.3 Gradle脚本应用的“构建配方”新手对Gradle又爱又怕。实际上它只是一个自动化构建工具你用它的目的只有三个管理依赖库、配置构建参数、打包生成APK。项目根目录的build.gradle是全局配置app/build.gradle才是每个模块的具体配置。看一段最常见的app/build.gradleplugins { id com.android.application id org.jetbrains.kotlin.android } android { namespace com.example.myapplication compileSdk 34 defaultConfig { applicationId com.example.myapplication minSdk 24 targetSdk 34 versionCode 1 versionName 1.0 } buildTypes { release { minifyEnabled false } } } dependencies { implementation androidx.core:core-ktx:1.12.0 implementation androidx.appcompat:appcompat:1.6.1 implementation com.google.android.material:material:1.11.0 }这里有几个字段值得花30秒理解compileSdk用哪个版本的SDK来编译代码一般用最新稳定版。minSdk应用最低支持Android几低于这个版本的设备装不了。targetSdk告诉系统这个应用针对某版本做过适配。Android系统版本升级时主要看targetSdk来决定是否启用新行为。applicationId应用的最终包名用于应用市场识别。dependencies你引用的第三方库。implementation表示编译和运行时都可用。我在带新人时发现一个高频误区以为依赖加得越多越好。实际上每引入一个库APK体积和构建时间都在涨有的库还会带来兼容性冲突。正确的做法是“用到什么加什么”不要囤积依赖。2.4 AndroidManifest.xml应用的“身份证”整个工程里最重要的文件很多人却经常忽略它。AndroidManifest.xml位于src/main目录下它向系统声明了应用的“身份信息”manifest xmlns:androidhttp://schemas.android.com/apk/res/android application android:labelstring/app_name android:iconmipmap/ic_launcher activity android:name.MainActivity intent-filter action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER / /intent-filter /activity /application /manifest关键的几件事全在这里面声明组件你写的Activity、Service、Receiver不在这里注册系统就不认识它。声明入口MAINaction LAUNCHERcategory 的Activity决定了桌面点击图标后启动哪个页面。声明权限比如需要访问网络要在manifest里加uses-permission android:nameandroid.permission.INTERNET/。新手最常见的报错之一就是新建了一个Activity但忘了注册运行时直接崩掉日志提示ClassNotFoundException或者ActivityNotRegistered。这也是为什么我反复强调“先看结构、后写代码”——很多坑其实都是结构认知不到位。3. 从系统层面看总体结构应用是怎么跑起来的3.1 从点击图标到界面显示系统做了什么现在把视角从工程目录拉高一层看看一个应用从你点下图标那一刻起系统是怎么让它跑起来的。很多人学Android只盯着自己写的代码却不知道系统框架在背后做了多少事遇到“为什么我的页面变黑了”“为什么服务突然被杀掉”这类问题就抓瞎。简化来说过程是这样的你点击桌面图标Launcher桌面应用通过Binder向系统服务ActivityManagerService发起启动Activity的请求。AMS验证信息后通知Zygote进程通过fork创建一个新的应用进程。Zygote是Android系统的“孵化器”所有应用进程都由它复制出来。新进程启动后系统在这个进程里创建并执行ActivityThread的main方法——这才是每个Android应用真正的“入口主函数”平时你在代码里看不到它因为框架帮你封装好了。ActivityThread通过AMS拿到要启动的Activity信息创建Activity实例调用onCreate生命周期方法加载布局文件最终把界面渲染到屏幕上。这个过程我想让读者记住一个核心概念Android应用不是“运行起来”的而是“被系统调度起来”的。App的每个组件都是被动创建、被动销毁一切生命周期都由系统控制。这跟写普通Java程序完全不一样普通程序自己掌控一切Android应用则是“系统说了算”。3.2 应用进程、系统服务与四大组件的协作关系再往深一层Android系统本身也是有结构的。我习惯把它分成四个层次来看Linux内核层硬件驱动、进程管理、内存管理。Android基于Linux内核这是系统稳定性的基础。系统服务层一堆运行在系统进程里的服务比如AMS管理Activity、WMS管理窗口、PMS管理安装包。这些服务是所有应用共享的“管家”。框架层SDK里提供的那一堆API比如Activity类、RecyclerView控件。你写的代码调用这些APIAPI内部最终通过Binder IPC和系统服务通信。应用层你写的App代码和系统预装的各种App都在这层。这里推荐新手理解一个机制Binder。它是Android里应用层和系统服务通信的核心机制本质上是一种高效IPC进程间通信方式。你写的startActivity(intent)最终是跨进程把请求传给AMS的。你不需要自己写Binder代码但理解“应用和系统服务不在同一个进程”这件事很重要——否则你会疑惑“为什么我说返回上一个Activity系统却不听我的还可能杀我的进程”。举个例子当你的App切到后台系统内存紧张时AMS可能直接回收你的进程。这不是bug这是Android系统保障前台应用流畅性的“主动策略”。不理解这个结构你就会以为是自己代码写错了。3.3 版本碎片化与适配意识聊系统结构就绕不开Android令人头疼的碎片化问题。直到今天市面上还有运行Android 6到Android 15的各种设备不同版本的系统行为差异很大。这里必须区分两个概念minSdk和targetSdk。新手经常搞混。minSdk是“最低门槛”决定哪些老设备能装targetSdk是“适配声明”决定系统以什么行为标准对待你的应用。比如Android 6引入了运行时权限Android 8引入了通知渠道Android 11限制了外部存储访问Android 12引入了沉浸式等新体验这些变化都需要你在targetSdk升级时同步适配。我接触过很多半路接手安卓项目的开发者最头疼的就是“为什么在Android 12上崩了在Android 10上没事”——大概率是targetSdk行为和代码没跟上。所以入门阶段就要培养一个习惯接手任何项目先看compileSdk和targetSdk再读官方适配文档。这个意识越早建立后面越省心。4. 新手高频问题与踩坑记录4.1 常见问题速查表我在带新人和回答社区提问时积累了下面这组高频问题几乎每个初学者都会遇到至少两三个。问题现象根本原因解决办法新建的Activity启动就崩溃没在AndroidManifest.xml中注册在application节点下加activity android:name.YourActivity/资源ID报红R类找不到资源文件有语法错误或资源名不符合规范检查res/下XML文件名和内容Clean Project后Rebuild图片、文件读不到文件放错目录或者路径硬编码资源放res/使用R.drawable.xxx引用不要硬编码绝对路径为什么Android/data目录打不开Android 11开始限制了外部存储的访问这是系统行为应用专属文件用Context.getExternalFilesDir()获取而不是写死路径依赖库下载慢或下载失败网络或仓库配置问题检查Gradle仓库镜像配置改用阿里云/腾讯云镜像仓库模拟器太卡内存分配不足或没有开启硬件加速AVD配置里增加内存确保SDK Manager里已安装Intel HAXM/Hypervisor改了代码点Run没变化Android Studio没重新构建或增量构建失效Build - Clean Project然后重新Run关于/storage/emulated/0/Android/data/这个目录我多说一句。很多人在网上搜索一些应用数据文件时会看到这个路径。这是一个应用专属外部存储目录每个应用只能访问自己名下对应包名的子目录这是Android的沙箱机制设计。从Android 11起连文件管理器App都默认不能直接访问这个目录下的其他应用数据。遇到“Operation not permitted”之类的错误不是你的设备坏了而是权限设计如此。正确做法是用应用的公开目录比如Downloads来共享文件或者通过系统提供的文件选择器SAF让用户授权。4.2 我踩过的几个坑说几个我自己最早学Android时踩得最深的坑希望能帮各位跳过。第一个坑是疯狂依赖教程不看SDK源码。我最初跟着教程写了一年多代码遇到问题才去查Stack Overflow很少直接打开Android SDK里的源码看。直到有一天在调试一个RecyclerView滑动异常时点进RecyclerView源码里看了一眼才发现很多“神奇行为”其实在源码注释里写得明明白白。建议大家从入门第一天起养成Ctrl点击、进源码看注释的习惯源码是最好的官方文档。第二个坑是不关注Gradle构建日志。很多新手报错只看红字看完就说“看不懂”。实际上Gradle构建失败时关键信息往往在红色日志上面的几行比如“duplicate resources”、某个依赖找不到、SDK版本不匹配。把这些关键词复制到搜索引擎比你苦思冥想快得多。后来我带新人第一件事就是教他们“学会读构建输出”这个能力比会写代码还重要。第三个坑是滥用e.printStackTrace()。刚开始学网络请求异常经常直接打堆栈就完了导致线上问题根本查不到。正确的习惯是异常要么抛出去让上层统一处理要么把关键信息用Log.i/tag的方式打出来并且带上上下文信息比如“请求失败urlxxx, codexxx”。这种看似“不核心”的习惯会成为你以后调试效率的分水岭。5. 认识总体结构之后接下来怎么学5.1 基于“总体结构”往下延伸的学习路径当你理解了应用由四大组件构成、工程目录各司其职、系统通过AMS调度应用下一步的学习方向就有了清晰的路线。我建议按下面这个顺序往下走每一步都在给“认识总体结构”添砖加瓦界面与布局学LinearLayout、RelativeLayout、ConstraintLayout掌握XML布局和控件的用法。这是最直观的一层成就感来得最快。生命周期把Activity从创建到销毁的完整生命周期和状态转弄明白。这是Android进阶的第一个分水岭不理解生命周期后面写网络请求和状态保存必然出bug。UI组件与列表RecyclerView是重头戏配合Adapter、ViewHolder、LayoutManager学这是几乎所有App的高频页面形态。数据存储SharedPreferences、Room数据库、文件存储理解应用数据的持久化方式开始建立“数据层”的概念。网络与异步Retrofit OkHttp 协程理解在Android里为什么不能在主线程做耗时操作以及如何安全地把数据从服务器带回界面。架构模式MVP、MVVM以及Jetpack组件体系ViewModel、LiveData、DataBinding。这一步开始从“能写”走向“会组织代码”。这条路径走完你已经具备独立开发一个中等复杂度App的能力。再往后是自定义View、性能优化、NDK、Flutter跨端之类的进阶方向可以按兴趣和职业目标选择。5.2 关键学习工具与资料工具方面除了Android Studio本体我建议尽早接触这几个东西ADB命令可以直接跟设备/模拟器交互看日志、传文件、查进程、Logcat过滤按Tag和级别精确看日志比在AS下方一坨红色里捞要高效得多、Memory Profiler检查内存泄漏和卡顿定位跟手度问题特别好用、官方文档 developer.android.com配合Android源码使用。资料方面我给三个明确建议第一优先看官方Training课程和API指南尤其“应用基础”和“构建第一个应用”那个系列第二找一本结构讲得清楚的书认真啃比看一百个短视频管用第三自己动手写日志每完成一个功能就总结一遍加深对结构的理解。最后分享一个我自己的习惯学Android不要只盯着“版本号”。业界每年都会讨论“该不该升级compileSdk”这类问题其实答案取决于你的项目适配成本。初学阶段请直接使用当前最新的稳定版Android Studio和SDK不用纠结兼容老版本——你已经知道minSdk控制下限真要在生产环境兼容旧设备那时候再回去做适配就有清晰的理论依据了。结构认知就是一种“底层思维”一旦建立起来以后不管学多少新库、记多少新API都不会乱。Android这些年的版本翻新、框架迭代万变不离其宗核心始终是组件被系统调度界面由资源驱动逻辑靠生命周期管理。把这几个骨架刻在脑子里Android开发的路会越走越顺。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进