目录
- 准备工作:搭建开发环境
- 安装 Android Studio
- 创建第一个项目
- Hello World - 你的第一个 Android 应用
- 运行项目
- 理解项目结构
- 修改欢迎文字
- 用户交互 - 创建一个简单的计算器
- 设计界面 (XML 布局)
- 编写逻辑 (Kotlin/Java 代码)
- 处理按钮点击事件
- 数据存储 - 创建一个“待办事项”应用
- 使用
RecyclerView显示列表 - 使用
EditText和Button添加新任务 - 使用
Room数据库持久化存储数据
- 使用
- 进阶学习路径
- 推荐资源
- 下一步该学什么
准备工作:搭建开发环境
在开始之前,你需要安装官方的集成开发环境。

安装 Android Studio
- 下载:访问 Android Developers 官网 下载适用于你操作系统的 Android Studio。
- 安装:像安装普通软件一样完成安装,安装过程中,它会自动下载所需的 Android SDK(软件开发工具包)和模拟器系统镜像,这可能需要一些时间,请耐心等待。
- 启动与配置:首次启动 Android Studio,它会引导你进行一些基本配置,比如导入设置、安装 SDK 组件等,按照提示一步步操作即可。
创建第一个项目
- 启动 Android Studio,点击 "New Project"。
- 选择模板,对于初学者,推荐选择 "Empty Views Activity",它提供了一个最简洁的起点。
- 配置你的项目:
- Name: 你的应用名称,"MyFirstApp"。
- Package name: 应用的唯一标识符,通常用反向域名格式,
com.example.myfirstapp。 - Save location: 项目保存的路径。
- Language: 选择 Kotlin(现代、官方推荐)或 Java(传统,但依然广泛使用),本教程将以 Kotlin 为主。
- Minimum SDK: 选择你的应用支持的最低 Android 版本,建议选择 API 24 或更高,以覆盖绝大多数设备。
- 点击 "Finish",Android Studio 会开始构建项目,同样需要一些时间。
实例一:Hello World - 你的第一个 Android 应用
你已经有了一个可以运行的项目,让我们来运行它,并稍微修改一下。
运行项目
- 在 Android Studio 顶部工具栏中,选择一个模拟器设备(如果没有,可以点击 "Create Device..." 创建一个)。
- 点击绿色的 "Run" 按钮(一个三角形图标)。
- 稍等片刻,模拟器会启动并显示你的应用,你应该能看到一个显示 "Hello World!" 的界面。
理解项目结构
在左侧的 Project 面板中,切换到 "Android" 视图,你会看到几个关键文件夹:
app/: 应用的主要代码和资源所在。manifests/:AndroidManifest.xml文件,是应用的“清单”,定义了应用的基本信息,如包名、权限、入口 Activity 等。java/: 存放你的 Kotlin 或 Java 代码。com.example.myfirstapp包下是你的主 Activity 文件,MainActivity.kt,Activity 是一个屏幕界面。res/: (resources) 存放所有非代码资源。layout/: 存放 XML 文件,用于定义 UI 布局。activity_main.xmlMainActivity对应的布局文件。mipmap-xxx/: 存放应用图标。values/: 存放字符串、颜色、样式等常量。strings.xml定义了应用中使用的文本。
修改欢迎文字
这是你第一次修改应用的 UI。
- 打开
res/layout/activity_main.xml文件,你会看到默认的代码视图。 - 切换到 "Split" 或 "Design" 视图,这样可以更直观地看到界面。
- 在中间的预览区域,找到显示 "Hello World!" 的
TextView。 - 在右侧的 Attributes(属性)面板中,找到
text属性。 - 点击它,或者直接双击布局文件中的
android:text="Hello World!"。 - 将其修改为
android:text="你好,Android!"。 - 重新运行应用(点击 Run 按钮),你会看到模拟器上的文字已经改变了。
恭喜!你已经成功修改了应用的界面。

实例二:用户交互 - 创建一个简单的计算器
这个实例将教你如何创建 UI 布局,并通过 Kotlin 代码响应用户操作。
目标
创建一个简单的计算器,可以输入两个数字,点击加法按钮后显示结果。
步骤 1:设计界面 (activity_main.xml)
打开 res/layout/activity_main.xml,使用 Design 视图或直接编写代码来创建以下布局:
- 两个
EditText用于输入数字。 - 一个
Button用于触发计算。 - 一个
TextView用于显示结果。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp"
tools:context=".MainActivity">
<EditText
android:id="@+id/number1EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入第一个数字"
android:inputType="number" />
<EditText
android:id="@+id/number2EditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="输入第二个数字"
android:inputType="number" />
<Button
android:id="@+id/calculateButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="计算" />
<TextView
android:id="@+id/resultTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="结果将显示在这里"
android:textSize="18sp" />
</LinearLayout>
关键点:
LinearLayout: 一种线性布局,orientation="vertical"表示垂直排列子元素。android:id: 为每个视图分配一个唯一的 ID,方便在代码中引用它。@+id/...表示这是一个新 ID。android:hint: 当EditText为空时显示的提示文本。android:inputType="number": 限制输入框只能输入数字。
步骤 2:编写逻辑 (MainActivity.kt)
现在打开 app/java/com.example.myfirstapp/MainActivity.kt,添加代码来处理点击事件。
package com.example.myfirstapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
class MainActivity : AppCompatActivity() {
// 1. 声明视图变量
private lateinit var number1EditText: EditText
private lateinit var number2EditText: EditText
private lateinit var calculateButton: Button
private lateinit var resultTextView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) // 关联布局文件
// 2. 通过 ID 找到视图并赋值给变量
number1EditText = findViewById(R.id.number1EditText)
number2EditText = findViewById(R.id.number2EditText)
calculateButton = findViewById(R.id.calculateButton)
resultTextView = findViewById(R.id.resultTextView)
// 3. 为按钮设置点击事件监听器
calculateButton.setOnClickListener {
// 在这里编写点击后要执行的代码
calculateSum()
}
}
// 4. 创建一个计算方法
private fun calculateSum() {
// 获取两个输入框的文本
val num1Str = number1EditText.text.toString()
val num2Str = number2EditText.text.toString()
// 检查输入是否为空
if (num1Str.isEmpty() || num2Str.isEmpty()) {
// 如果为空,显示一个提示
Toast.makeText(this, "请输入数字!", Toast.LENGTH_SHORT).show()
return
}
// 将字符串转换为数字
val num1 = num1Str.toDouble()
val num2 = num2Str.toDouble()
// 计算和
val sum = num1 + num2
// 将结果显示在 TextView 上
resultTextView.text = "计算结果是: $sum"
}
}
代码解释:
lateinit var: 声明一个非空的变量,但稍后再初始化,这是在onCreate中通过findViewById初始化它们的常用方式。findViewById(R.id.xxx): 通过在 XML 中定义的 ID 来获取对应的视图对象。setOnClickListener: 为按钮设置一个监听器,当用户点击按钮时,大括号 中的代码块就会被执行。calculateSum(): 我们把核心计算逻辑放在一个单独的函数里,让代码更清晰。text.toString(): 从EditText获取的是Editable对象,需要转换成String。Toast.makeText(...).show(): 显示一个临时的、悬浮在屏幕上的提示信息,非常适合用于反馈。
运行测试
运行应用,你应该能看到一个功能完整的计算器界面了!
实例三:数据存储 - 创建一个“待办事项”应用
这个实例将教你如何使用列表显示数据,并使用数据库将数据永久保存下来。
目标
创建一个可以添加、显示待办事项的应用,并且关闭应用后重新打开,数据依然存在。
步骤 1:添加依赖 (Room 数据库)
Room 是 Google 官方推荐的一个 ORM(对象关系映射)库,可以让你更轻松地操作 SQLite 数据库。
- 打开
app/build.gradle.kts(或app/build.gradle) 文件。 - 在
dependencies代码块中添加以下依赖:
// Room def room_version = "2.6.1" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" // Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:$room_version" // Coroutines (用于异步操作数据库) implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
注意:如果你使用的是
build.gradle(非 KTS DSL),依赖语法略有不同,确保在文件顶部有apply plugin: 'kotlin-kapt'。
- 点击 Android Studio 顶部出现的 "Sync Now" 按钮同步项目。
步骤 2:创建数据实体
创建一个 Kotlin 数据类,它代表了数据库中的一张表。
- 在
app/java/com.example.myfirstapp包下,右键 -> New -> Kotlin Class/File。 - 选择 "Data Class",命名为
Todo.kt。 - 添加以下代码:
package com.example.myfirstapp
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "todos") // @Entity 表示这是一个数据库表
data class Todo(
@PrimaryKey(autoGenerate = true) val id: Int = 0, // 主键,自动增长
val text: String // 待办事项的文本内容
)
步骤 3:创建 DAO (Data Access Object)
DAO 是一个接口,定义了如何查询、插入、更新和删除数据库中的数据。
- 在同一个包下,创建一个新的 "Interface",命名为
TodoDao.kt。 - 添加以下代码:
package com.example.myfirstapp
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
@Dao // @Dao 表示这是一个数据访问对象
interface TodoDao {
// @Insert 表示这是一个插入方法
// onConflict = OnConflictStrategy.REPLACE 表示如果主键冲突,则替换旧数据
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(todo: Todo)
// @Query 表示这是一个查询方法
// "SELECT * FROM todos" 是标准的 SQL 查询语句
// LiveData 表示查询结果是可观察的,当数据变化时,UI 会自动更新
@Query("SELECT * FROM todos ORDER BY id DESC")
fun getAllTodos(): LiveData<List<Todo>>
}
步骤 4:创建数据库
创建一个抽象类,作为数据库的入口点,并将实体和 DAO 关联起来。
- 在同一个包下,创建一个新的 "Abstract Class",命名为
AppDatabase.kt。 - 添加以下代码:
package com.example.myfirstapp
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [Todo::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun todoDao(): TodoDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"todo_database"
).build()
INSTANCE = instance
instance
}
}
}
}
步骤 5:修改布局 (activity_main.xml)
我们需要一个 RecyclerView 来显示列表,以及一个 EditText 和 Button 来添加新任务。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:padding="8dp">
<EditText
android:id="@+id/todoEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="输入新任务..." />
<Button
android:id="@+id/addButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="添加" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp" />
</LinearLayout>
步骤 6:创建列表项布局
创建一个 XML 文件来定义列表中每一项的样式。
- 在
res/layout目录下,右键 -> New -> Layout Resource File。 - 文件名命名为
item_todo.xml。 - 设计一个简单的布局,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/todoTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp" />
</LinearLayout>
步骤 7:创建适配器
适配器是连接 RecyclerView 和数据源的桥梁。
- 在包下,创建一个新的 "Class",命名为
TodoAdapter.kt。 - 添加以下代码:
package com.example.myfirstapp
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class TodoAdapter(private val todos: List<Todo>) : RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {
//ViewHolder 持有列表项的视图
class TodoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val todoTextView: TextView = itemView.findViewById(R.id.todoTextView)
}
// 创建新的 ViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_todo, parent, false)
return TodoViewHolder(view)
}
// 绑定数据到 ViewHolder
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
val todo = todos[position]
holder.todoTextView.text = todo.text
}
// 返回数据总数
override fun getItemCount() = todos.size
}
步骤 8:修改 MainActivity.kt 整合所有功能
这是最复杂的一步,我们将把所有组件连接起来。
package com.example.myfirstapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var todoEditText: EditText
private lateinit var addButton: Button
private lateinit var recyclerView: RecyclerView
// 使用 ViewModel 来管理 UI 相关的数据
private val todoViewModel: TodoViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 初始化视图
todoEditText = findViewById(R.id.todoEditText)
addButton = findViewById(R.id.addButton)
recyclerView = findViewById(R.id.recyclerView)
// 设置 RecyclerView
val adapter = TodoAdapter(emptyList()) // 先用空列表初始化
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
// 观察数据库中的数据变化
todoViewModel.allTodos.observe(this, Observer { todos ->
// 当数据变化时,更新适配器
todos?.let { adapter.updateData(it) }
})
// 设置添加按钮的点击事件
addButton.setOnClickListener {
val todoText = todoEditText.text.toString()
if (todoText.isNotEmpty()) {
val todo = Todo(text = todoText)
// 在后台线程插入数据
todoViewModel.insert(todo)
todoEditText.text.clear() // 清空输入框
}
}
}
}
步骤 9:创建 ViewModel
ViewModel 用于保存和管理与 UI 相关的数据,以便在配置更改(如屏幕旋转)时数据不会丢失。
- 在包下,创建一个新的 "Class",继承自
AndroidViewModel,命名为TodoViewModel.kt。 - 添加以下代码:
package com.example.myfirstapp
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class TodoViewModel(application: Application) : AndroidViewModel(application) {
private val todoDao: TodoDao
val allTodos: LiveData<List<Todo>>
init {
val database = AppDatabase.getDatabase(application)
todoDao = database.todoDao()
allTodos = todoDao.getAllTodos()
}
fun insert(todo: Todo) {
viewModelScope.launch {
todoDao.insert(todo)
}
}
}
步骤 10:修改适配器以支持数据更新
为了让 TodoAdapter 能够接收新数据,我们需要添加一个 updateData 方法。
打开 TodoAdapter.kt,在类中添加:
// 在 TodoAdapter 类中添加这个方法
fun updateData(newTodos: List<Todo>) {
// 这里为了简化,我们直接创建一个新的适配器实例
// 在实际项目中,可以使用 DiffUtil 来高效地更新列表
// 这是一个简单的演示
this.todos = newTodos
notifyDataSetChanged()
}
注意:上面的
updateData方法比较简单,在生产环境中,推荐使用ListAdapter或AsyncPagingDataListAdapter配合DiffUtil,它们能更高效地处理列表更新。
最后一步:在 AndroidManifest.xml 中添加 android:exported="true"
为了让其他应用可以启动你的 Activity(在从通知等地方启动时可能需要),或者在较新的 Android 版本上避免一些警告,打开 app/manifests/AndroidManifest.xml,找到 <activity> 标签,添加 android:exported="true" 属性。
<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>
运行测试
运行你的应用!你应该可以:
- 在输入框中输入文字,点击“添加”按钮。
- 新的任务会立即出现在下方的列表中。
- 关闭应用,然后重新打开,你会发现之前添加的任务依然存在!
恭喜!你已经掌握了 Android 开发中最核心的几个概念:UI 布局、用户交互、数据列表和本地数据持久化。
进阶学习路径
恭喜你完成了这三个实例!你已经具备了坚实的基础,你可以探索以下方向来提升自己:
- 导航组件: 学习使用 Jetpack Navigation 来管理多个页面之间的跳转和返回栈,让应用导航更流畅。
- 生命周期和作用域: 深入理解 Activity/Fragment 的生命周期,以及 Kotlin 的
lifecycleScope和viewModelScope如何帮助你管理后台任务,避免内存泄漏。 - 依赖注入: 学习使用 Hilt 或 Koin 等框架来管理对象的生命周期和依赖关系,让代码更易于测试和维护。
- 网络请求: 使用 Retrofit 和 OkHttp 库从网络获取数据(从 API 获取新闻)。
- 图片加载: 使用 Glide 或 Coil 库高效地加载和显示网络图片。
- 工作管理器: 学习使用 WorkManager 来安排需要在后台执行的任务,即使应用关闭或重启,任务也能可靠执行。
- Material Design 3: 学习使用 Google 的 Material Design 设计语言,让你的应用看起来更现代、更美观。
推荐资源
- 官方文档: developer.android.com 是最权威、最准确的资料。
- Android Codelabs: Google 提供的一系列动手编码教程,质量很高。
- GitHub: 查看优秀的开源项目,学习别人的代码风格和架构。
- 技术博客: 遵循一些知名的 Android 开发者或团队的博客。
持续学习和实践是成为优秀开发者的关键,祝你学习愉快!
