项目结构
了解采用MVVM架构构建的Android应用程序的项目结构。
上图展示了我们将用于学习MVVM架构的App结构。该应用名为 GlobalNewsApp,主要功能是展示新闻文章列表。其具备以下特性:
- 文章列表展示:应用应显示文章列表。
- 分页加载:这是一个允许我们每次仅在屏幕上加载少量数据的库。在本应用中,文章列表被拆分为更小的块,逐次加载,从而实现流畅的滚动效果,提升用户体验。
- WebView:允许用户在应用内点击文章进行阅读。
- 收藏文章功能:用户可选择自己喜欢的文章,稍后在线或离线阅读,此功能将充分利用
Room数据库。 - 离线功能:当设备处于离线状态时,应用会从
Room本地数据库加载最近查看过的文章列表到用户界面,并在重新连接互联网时更新为最新的文章列表。 - 搜索功能:支持搜索特定文章或主题。
项目文件
在Android中,文件按模块组织,我们的 NewsApplication 仅包含一个模块——app模块。但根据应用的规模和架构,我们可以添加任意数量的模块。接下来深入分析这些模块。
代码结构
下图展示了我们的项目结构。
上图展示了我们将用于学习MVVM架构的App结构。应用名称为 GlobalNewsApp,主要功能是展示新闻文章列表,具体特性如下:
- 文章列表展示:应用应显示文章列表。
- 分页加载:这是一个允许我们每次仅在屏幕上加载少量数据的库。在本应用中,文章列表被拆分为更小的块,逐次加载,从而实现流畅的滚动效果,提升用户体验。
- WebView:允许用户在应用内点击文章进行阅读。
- 收藏文章功能:用户可选择自己喜欢的文章,稍后在线或离线阅读,此功能将充分利用
Room数据库。 - 离线功能:当设备处于离线状态时,应用会从
Room本地数据库加载最近查看过的文章列表到用户界面,并在重新连接互联网时更新为最新的文章列表。 - 搜索功能:支持搜索特定文章或主题。
项目文件
在Android中,文件按模块组织,我们的 NewsApplication 仅包含一个模块——app模块。但根据应用的规模和架构,我们可以添加任意数量的模块。接下来深入分析这些模块。
App:这是我们的模块,作为源文件的容器,按不同功能划分,支持项目的测试与调试。Manifest:这是一个XML文件,包含应用的重要元数据,如权限、图标、应用名称、启动活动等。
1<?xml version="1.0" encoding="utf-8"?> 2<manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.globalnewsapp"> 4 5 <uses-permission android:name="android.permission.INTERNET" /> 6 7 <application 8 android:allowBackup="true" 9 android:icon="@drawable/news" 10 android:label="@string/app_name" 11 android:roundIcon="@mipmap/ic_launcher_round" 12 android:supportsRtl="true" 13 android:theme="@style/Theme.GlobalNewsApp"> 14 <activity 15 android:name=".ui.NewsActivity" 16 android:exported="true" /> 17 <activity 18 android:name=".SplashScreenActivity" 19 android:exported="true"> 20 <intent-filter> 21 <action android:name="android.intent.action.MAIN" /> 22 23 <category android:name="android.intent.category.LAUNCHER" /> 24 </intent-filter> 25 </activity> 26 27 <meta-data 28 android:name="preloaded_fonts" 29 android:resource="@array/preloaded_fonts" /> 30 </application> 31 32</manifest>
java:存放所有源代码,按包和类组织。res:存放非代码资源,如XML布局、图片、视频、字体和图标。gradle:高级构建工具,用于自动化和管理构建流程。APK文件通过此系统生成,分为两类:- 项目级Gradle:位于根项目目录,用于定义适用于所有模块的依赖项。使用
buildscript{}块来声明必要的依赖和仓库。
- 项目级Gradle:位于根项目目录,用于定义适用于所有模块的依赖项。使用
1buildscript { 2 ext.kotlin_version = '1.3.72' 3 repositories { 4 google() 5 mavenCentral() 6 } 7 dependencies { 8 classpath "com.android.tools.build:gradle:7.0.4" 9 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30" 10 classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-alpha03" 11 12 // 注意:不要在此处放置应用依赖;它们应在各个模块的build.gradle文件中 13 } 14} 15 16task clean(type: Delete) { 17 delete rootProject.buildDir 18}
- 模块级Gradle文件:用于每个模块的具体配置,位于项目各模块中。包含以下内容:
1apply plugin: 'com.android.application' 2apply plugin: 'kotlin-android' 3apply plugin: 'kotlin-kapt' 4apply plugin: 'androidx.navigation.safeargs' 5 6def localPropertiesFile = rootProject.file("local.properties") 7def localProperties = new Properties() 8localProperties.load(new FileInputStream(localPropertiesFile)) 9 10 11android { 12 compileSdkVersion 31 13 buildToolsVersion "29.0.3" 14 15 defaultConfig{ 16 buildConfigField "String", "NEWS_API_KEY", localProperties['news_access_key'] 17 } 18 19 buildFeatures { 20 viewBinding true 21 } 22 23 defaultConfig { 24 25 configurations.all { 26 resolutionStrategy { force 'androidx.core:core-ktx:1.7.0' } 27 } 28 29 applicationId "com.example.globalnewsapp" 30 minSdkVersion 21 31 targetSdkVersion 31 32 versionCode 1 33 versionName "1.0" 34 multiDexEnabled true 35 36 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 37 } 38 39 buildTypes { 40 release { 41 minifyEnabled false 42 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 43 } 44 } 45 compileOptions { 46 sourceCompatibility JavaVersion.VERSION_1_8 47 targetCompatibility JavaVersion.VERSION_1_8 48 } 49 kotlinOptions { 50 jvmTarget = '1.8' 51 } 52} 53 54dependencies { 55 56 implementation 'androidx.core:core-ktx:1.7.0' 57 //noinspection GradleDependency 58 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 59 implementation 'androidx.appcompat:appcompat:1.4.0' 60 implementation 'com.google.android.material:material:1.4.0' 61 implementation 'androidx.constraintlayout:constraintlayout:2.1.2' 62 implementation 'androidx.legacy:legacy-support-v4:1.0.0' 63 testImplementation 'junit:junit:4.13.2' 64 androidTestImplementation 'androidx.test.ext:junit:1.1.3' 65 androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 66 67 68 // 架构组件 69 implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0" 70 implementation 'androidx.appcompat:appcompat:1.4.0' 71 72 // Room 73 implementation "androidx.room:room-runtime:2.3.0" 74 kapt "androidx.room:room-compiler:2.3.0" 75 76 // Kotlin扩展和协程支持 77 implementation "androidx.room:room-ktx:2.3.0" 78 79 // 协程 80 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1' 81 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.1' 82 83 // 协程生命周期作用域 84 implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0" 85 implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0" 86 87 // Retrofit 88 implementation 'com.squareup.retrofit2:retrofit:2.9.0' 89 implementation 'com.squareup.retrofit2:converter-gson:2.9.0' 90 implementation "com.squareup.okhttp3:logging-interceptor:4.9.0" 91 92 // 导航组件 93 implementation "androidx.navigation:navigation-fragment-ktx:2.3.5" 94 implementation "androidx.navigation:navigation-ui-ktx:2.3.5" 95 96 // Glide 97 implementation 'com.github.bumptech.glide:glide:4.12.0' 98 kapt 'com.github.bumptech.glide:compiler:4.11.0' 99 100 implementation "androidx.core:core-ktx:1.7.0" 101 102}
compileSdkVersion 定义了Gradle用于编译应用的Android SDK版本。Android SDK是一套用于开发Android应用的工具集。每个新版本的SDK通常带来新功能和改进,以提升开发体验。例如,Android 12(SDK版本31)引入了无需使用Activity即可创建启动画面的新方式。
设置新的Android SDK
- 点击 工具 > SDK管理器。
- 在“SDK平台”选项卡中,选择Android 12。
- 在“SDK工具”选项卡中,选择Android SDK构建工具31。
- 点击“确定”安装SDK。
targetSdkVersion 定义了应用经过测试和设计所针对的Android SDK版本。该值可以等于或低于 compileSdkVersion,但绝不能更高,因为我们在编译时无法针对未知的版本进行适配。讨论目标版本时,需理解两个关键概念:向前兼容性和向后兼容性。
向前兼容性指应用设计为在较低版本(如Android 9.0,API级别28)上运行,而用户在较高版本(如Android 12)上运行时,旧版功能仍能正常工作,不会导致崩溃。
向后兼容性则相反:若目标SDK版本较高而平台版本较低,则高版本功能将在旧系统上尽可能平滑地运行,如同在新系统上一样。
minSdkVersion 决定了应用可在多少受限的Android设备上安装,或代码兼容的最低设备范围。Google Play商店以此作为判断应用可在哪些设备上安装的标准。
构建类型:在Android Studio中创建项目时,有两种构建类型:debug和release。
- Debug:用于直接运行到设备或使用模拟器进行测试。
- Release:已签名并分发至Play商店的构建版本,代码受到反向工程保护。
1buildTypes { 2 release { 3 minifyEnabled false 4 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 5 } 6}
配置Android Studio
学习如何在项目中集成项目级和模块级依赖。
打开Android Studio并开始操作。
- 从文件菜单选择“新建项目”。
- 选择“空白活动”。
- 新建项目、新建活动选项卡。
- 将项目命名为
NewsApp。 - 选择Kotlin作为编程语言。
- 最低SDK级别设为21,其余保持默认。
- Android Studio 新建项目选项卡。
- 成功完成Gradle同步后,项目即准备就绪。
- 新闻应用默认文件
项目级依赖
由于Android Studio版本差异,依赖同步方式略有不同。若您使用的是Bumblebee | 2021.1.1 或 Chipmunk | 2021.2.1 版本,您在项目级build Gradle中可能看到如下内容:
main.kt
build.gradle
- 将项目命名为
NewsApp。 - 选择Kotlin作为编程语言。
- 最低SDK级别设为21,其余保持默认。
- 成功完成Gradle同步后,项目即准备就绪。
项目级依赖
由于Android Studio版本差异,依赖同步方式略有不同。若您使用的是Bumblebee | 2021.1.1 或 Chipmunk | 2021.2.1 版本,您在项目级build Gradle中可能看到如下内容:
1#include <iostream> 2using namespace std; 3 4int main() { 5 // 您的代码放在这里 6 cout << "Hello World"; 7 return 0; 8}
若使用较旧版本,则应为:
1buildscript { 2 ext.kotlin_version = '1.3.72' 3 repositories { 4 google() 5 mavenCentral() 6 } 7 dependencies { 8 classpath "com.android.tools.build:gradle:7.0.4" 9 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30" 10 11 // 添加的依赖 12 classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-alpha03" 13 14 // 注意:不要在此处放置应用依赖;它们应在各个模块的build.gradle文件中 15 } 16} 17 18task clean(type: Delete) { 19 delete rootProject.buildDir 20}
在所有Android Studio版本中,模块级Gradle文件内容一致。提前说明这一点的原因是:若在任一版本中错误添加依赖,将引发难以排查的错误。因此,我们将在Android Studio中统一添加依赖,确保所有人处于同一进度。
添加依赖
这是我们要添加到项目级Gradle的依赖。若您使用的是Bumblebee | 2021.1.1 及以上版本,请使用 id 而非 classpath 添加。
依赖项:id 'androidx.navigation.safeargs.kotlin' version '2.5.0-alpha01' apply false
请按如下方式添加:
1// 项目级构建文件,可用于为所有子项目/模块添加通用配置 2plugins { 3 id 'com.android.application' version '7.1.1' apply false 4 id 'com.android.library' version '7.1.1' apply false 5 id 'org.jetbrains.kotlin.android' version '1.6.10' apply false 6 7 // 添加的依赖 8 id 'androidx.navigation.safeargs.kotlin' version '2.5.0-alpha01' apply false 9} 10 11task clean(type: Delete) { 12 delete rootProject.buildDir 13}
若您使用的是较旧版本,请使用 classpath 而非 id,如下所示:
1// 项目级构建文件,可用于为所有子项目/模块添加通用配置 2buildscript { 3 ext.kotlin_version = '1.3.72' 4 repositories { 5 google() 6 mavenCentral() 7 } 8 dependencies { 9 classpath "com.android.tools.build:gradle:7.0.4" 10 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30" 11 12 // 添加的依赖 13 classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-alpha03" 14 15 // 注意:不要在此处放置应用依赖;它们应在各个模块的build.gradle文件中 16 } 17} 18 19task clean(type: Delete) { 20 delete rootProject.buildDir 21}
错误提示
若未遵循上述配置,可能会遇到以下错误。请务必确认代码与上述内容一致。

我们刚刚添加的Navigation组件是一个UI库,简化了在应用不同页面间导航的代码编写。它是Jetpack组件的一部分,使我们能够使用Fragment进行页面跳转,不再依赖传统的Intent和事务。现在我们通过图形和目的地来定义导航动作和目标。
模块级依赖
这些是将在程序中编译并同步的模块级依赖。
main.kt
build.gradle
1#include <iostream> 2using namespace std; 3 4int main() { 5 // 您的代码放在这里 6 cout << "Hello World"; 7 return 0; 8}
添加上述依赖后,点击“同步”以构建项目。
若遇到Gradle错误,请仔细阅读错误信息,并对照我们提供的代码片段检查是否一致,再尝试重新构建。
No configuration found for ID: 3e7f36f1892b52a7c1953b0fb7eca7e6ec4b775f0fff1a1737d8ed8478685398
若在添加依赖时未出现错误,这就是我们的应用将显示的效果。