第2章:Android项目结构解析

说实话,很多初学者拿到一个Android项目,第一反应就是懵。文件夹一堆,文件一堆,到底哪个是干嘛的?我当年刚入行时也是这样,打开Android Studio新建项目,看着满屏的目录结构,心里直打鼓。今天我就带你把这些东西捋清楚。

2.1 项目目录结构

一个标准的Android项目,大致长这样:

MyApplication/
├── app/
│   ├── src/
│   │   ├── main/
│   │   │   ├── java/com/example/myapp/
│   │   │   │   ├── MainActivity.java
│   │   │   │   └── ...
│   │   │   ├── res/
│   │   │   │   ├── layout/
│   │   │   │   ├── drawable/
│   │   │   │   ├── values/
│   │   │   │   └── ...
│   │   │   └── AndroidManifest.xml
│   │   ├── test/
│   │   └── androidTest/
│   ├── build.gradle
│   └── ...
├── gradle/
├── build.gradle
├── settings.gradle
└── gradle.properties

嗯,看着挺多,但核心就几个部分。我习惯把项目结构分成三层来理解:

  • 项目根目录:负责全局配置,比如Gradle版本、仓库地址
  • app模块:你的代码、资源、清单文件全在这
  • Gradle相关:构建脚本,控制编译、打包、依赖

你想想看,app模块才是我们真正干活的地方。其他那些gradle文件,说白了就是告诉系统「怎么编译这个app」。

重点:src/main/java 放Java/Kotlin代码,src/main/res 放资源文件,AndroidManifest.xml 是应用的「身份证」。

2.2 Gradle构建系统

Gradle这东西,我第一次接触时也觉得挺玄乎。后来发现,它就是个自动化构建工具。你写代码,它帮你编译、打包、签名、生成APK。

项目中至少有两个build.gradle文件:

项目级build.gradle(根目录):

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
    }
}

模块级build.gradle(app目录):

plugins {
    id 'com.android.application'
}

android {
    compileSdk 33
    defaultConfig {
        applicationId "com.example.myapp"
        minSdk 21
        targetSdk 33
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.0'
    implementation 'com.google.android.material:material:1.8.0'
}

我个人习惯把依赖版本号抽出来,放到一个单独的gradle文件中管理。这样多个模块共享依赖时,改一处就行。曾经有个项目,因为依赖版本不一致,折腾了我整整一个下午。

小技巧:minSdk 和 targetSdk 这两个值要慎重。minSdk 设得太高,用户少;设得太低,你得兼容老版本的各种坑。我一般建议 minSdk 设为 21,覆盖了95%以上的设备。

2.3 AndroidManifest.xml详解

这个文件,我称之为「应用的户口本」。系统启动你的app前,先读这个文件,看看你有哪些组件、需要什么权限。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.MyApplication">

        <activity android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

这里有几个关键点:

  • package:应用的唯一标识,发布后不能改
  • uses-permission:声明需要的权限,比如网络、相机
  • activity:注册Activity组件,intent-filter指定入口
  • exported:这个属性在Android 12之后必须显式声明

我曾经踩过一个坑:忘记在Manifest里注册Activity,结果运行时直接崩溃。系统提示「ActivityNotFoundException」,当时找了半天才反应过来。嗯,这种低级错误,犯过一次就记住了。

注意:Android 12(API 31)开始,如果Activity包含intent-filter,exported必须设为true。否则系统会拒绝启动这个Activity。

2.4 资源文件管理

资源文件放在res目录下,系统会根据文件名和目录名自动生成R.id、R.layout等引用。说白了,你写代码时用的那些R.xxx,都是从这里来的。

目录 用途 常见文件
res/layout 界面布局 activity_main.xml
res/drawable 图片、形状 ic_launcher.png
res/values 字符串、颜色、主题 strings.xml, colors.xml
res/mipmap 应用图标 ic_launcher.webp
res/menu 菜单布局 main_menu.xml

资源文件有个好处:支持多屏幕适配。比如你在res/layout-sw600dp下放一个布局,系统在平板设备上会自动加载这个布局。我做过一个项目,手机和平板共用一套代码,就是靠这种资源限定符实现的。

另外,字符串资源一定要写在strings.xml里,不要硬编码在Java代码中。为什么?因为后续做国际化时,你只需要添加对应的values-zh、values-en目录就行了。硬编码的话,改起来能让你怀疑人生。

最佳实践:所有文本、颜色、尺寸都定义在res/values中。代码里只引用R.string.xxx、R.color.xxx。这样后期维护、换肤、国际化都方便。

好了,项目结构这块就讲这么多。你只要记住:代码在java目录,资源在res目录,配置在Manifest和Gradle里。这三块搞明白了,Android项目对你来说就没啥秘密了。