§1 Android 开发环境相关
1. Android / API / SDK 概念
| 术语 | 含义 |
|---|---|
| Android | Google 主导的基于 Linux 内核的移动操作系统,采用分层架构(Linux Kernel → HAL → Native Libraries / Android Runtime → Framework API → System Apps) |
| API Level | 框架 API 的整型版本号。每个 Android 版本对应一个 API Level(如 Android 13 = API 33)。minSdkVersion 决定最低兼容版本,targetSdkVersion 决定行为适配版本 |
| SDK | Software Development Kit,含 android.jar(Framework API)、build-tools(aapt/d8/zipalign)、platform-tools(adb/fastboot)、模拟器镜像、源码文档 |
2. Android 应用程序开发环境
- IDE: Android Studio(基于 IntelliJ IDEA)
- 构建工具链: Gradle → aapt2 编译资源 → javac/kotlinc → d8 字节码 → apksigner 签名
- 调试 : adb(Android Debug Bridge),通过 USB/WiFi 连接设备,
adb logcat、adb install、adb shell - 虚拟机: AVD(Android Virtual Device),需配置 CPU/ABI(x86_64 或 arm64-v8a)、系统镜像、内存/存储大小
3. AndroidManifest.xml 作用
manifest 是每个 Android 应用的入口声明文件,负责:
- 包名声明 :
package="com.example.app"(唯一标识) - 组件注册 : 四大组件(Activity、Service、BroadcastReceiver、ContentProvider)必须在此声明,否则运行时报
ActivityNotFoundException - 权限声明 :
<uses-permission>声明需要申请的权限,<permission>自定义权限 - 硬件特性 :
<uses-feature>声明需要的硬件(如摄像头、GPS) - 应用入口 :
<intent-filter>中声明MAIN+LAUNCHER的 Activity 作为桌面图标入口 - 最低 SDK 版本 :
<uses-sdk android:minSdkVersion="26" android:targetSdkVersion="34" />
4. Gradle Scripts
- settings.gradle : 声明项目包含的模块名
include ':app' - build.gradle(项目级): 配置全局仓库(google()/mavenCentral())和 AGP(Android Gradle Plugin)版本
- build.gradle(模块级): 核心构建配置
groovy
android {
namespace "com.example.app" // 应用命名空间
compileSdk 34 // 编译 SDK 版本
defaultConfig {
applicationId "com.example.app" // APP 唯一 ID
minSdk 26 // 最低兼容版本
targetSdk 34 // 目标适配版本
versionCode 1 // 内部版本号
versionName "1.0" // 外部版本名称
}
}
dependencies {
implementation "androidx.core:core-ktx:1.12.0" // 依赖
testImplementation "junit:junit:4.13.2" // 测试依赖
}
implementationvsapi: implementation 依赖不传递,api 依赖传递compileOnly: 仅编译期有效,不打包进 APKannotationProcessor: 注解处理器依赖
§2 Activity 与 Intent
1. Activity 生命周期
标准 7 个回调:
onCreate() → onStart() → onResume() → [Activity 运行中]
↓
onPause()
/ \
onResume() onStop()
/ \
onRestart() onDestroy()
| 回调 | 时机 | 能做什么 |
|---|---|---|
onCreate() |
Activity 首次创建 | setContentView() 加载布局,初始化变量,findViewById |
onStart() |
即将可见 | 注册监听,UI 可见前准备 |
onResume() |
前台获取焦点 | 开启动画、相机、传感器等前台资源 |
onPause() |
失去焦点(如弹框覆盖) | 保存数据、暂停动画/传感器(必须快速完成) |
onStop() |
完全不可见 | 释放重量级资源 |
onRestart() |
从 stop→start | 重新加载数据 |
onDestroy() |
Activity 销毁 | 最终清理,解除所有绑定 |
常见场景走了哪些回调:
- A 启动 B:A.onPause → B.onCreate → B.onStart → B.onResume → A.onStop
- 按 Home 键:onPause → onStop
- 旋转屏幕:onPause → onStop → onDestroy → onCreate → onStart → onResume(默认重建)
2. Intent 组件作用
Intent 是 Android 四大组件之间的通信信使:
| 作用 | 说明 |
|---|---|
| 页面跳转 | startActivity(intent) 启动另一个 Activity |
| 数据传递 | putExtra("key", value) 携带数据,目标页用 getStringExtra("key") 接收 |
| 启动 Service | startService(intent) 或 bindService(intent, ...) |
| 发送广播 | sendBroadcast(intent) |
| 调用系统功能 | 拨号 ACTION_DIAL、拍照 ACTION_IMAGE_CAPTURE、打开网页 ACTION_VIEW |
显式 Intent vs 隐式 Intent:
- 显式:直接指定目标组件类名
Intent(this, TargetActivity::class.java) - 隐式:通过 action/data/category 匹配,系统找到合适的组件处理
3. Intent 实现页面跳转的方法
java
// 方式一:显式 Intent
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("username", "张三");
startActivity(intent);
// 方式二:隐式 Intent
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);
// 方式三:带返回值的跳转
Intent intent = new Intent(this, EditActivity.class);
startActivityForResult(intent, REQUEST_CODE); // 已废弃,改用 ActivityResultLauncher
// 方式四:在 Intent 中指定 Action 和 Category
Intent intent = new Intent("com.example.MY_ACTION");
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
4. 组件声明(清单文件)
四大组件必须全部在 AndroidManifest.xml 中声明,否则抛出异常:
xml
<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>
<service android:name=".MyService" />
<receiver android:name=".MyReceiver" android:exported="true" />
<provider android:name=".MyProvider" android:authorities="com.example.provider" />
android:exported: Android 12+ 强制声明,表示是否允许其他应用访问- 只有动态注册的 BroadcastReceiver 可以不写 manifest
§4 Android 界面布局 / 控件
1. 常用布局容器
| 布局 | 特点 |
|---|---|
| LinearLayout | 线性排列,orientation="vertical" 垂直 / horizontal 水平 |
| RelativeLayout | 相对布局,控件相对于父容器或兄弟控件定位 |
| ConstraintLayout | 约束布局(Google 推荐默认),通过约束关系定位,扁平化 |
| FrameLayout | 帧布局,子控件层叠堆放,常用作 fragment 容器 |
| TableLayout | 表格布局,配合 TableRow 使用 |
2. TableLayout → TableRow 的结构
TableLayout 类似 HTML <table>,每行是一个 TableRow:
xml
<TableLayout ...>
<TableRow android:layout_height="wrap_content">
<TextView android:text="姓名" android:layout_column="0" />
<EditText android:layout_column="1" android:layout_span="2" />
</TableRow>
<TableRow ...>
<Button android:text="确定" />
</TableRow>
</TableLayout>
关键属性:
android:stretchColumns:拉伸指定列(如"0"拉伸第一列)android:shrinkColumns:收缩指定列android:layout_column:指定控件所在列android:layout_span:跨列数量
3. 相对布局 RelativeLayout
控件位置通过相对关系描述:
| 属性 | 含义 |
|---|---|
android:layout_alignParentTop/Bottom/Left/Right |
贴父容器边缘 |
android:layout_centerInParent |
父容器正中央 |
android:layout_above="@id/btn" |
在某个控件上方 |
android:layout_below="@id/btn" |
在某个控件下方 |
android:layout_toLeftOf / layout_toRightOf |
在某个控件左/右侧 |
android:layout_alignTop="@id/btn" |
与某个控件顶对齐 |
android:layout_alignBaseline="@id/tv" |
文字基线对齐 |
ID 的声明方式:android:id="@+id/my_button" → 在 R.java 中生成引用。
4. 线性布局 LinearLayout
- 垂直排列 :
android:orientation="vertical"→ 控件从上到下依次排列 - 水平排列 :
android:orientation="horizontal"→ 控件从左到右依次排列 - 权重分配 :
android:layout_weight="1",按比例分配剩余空间(weight 越大占比越大)
注意 : 使用 weight 时,对应方向的宽/高应设为 0dp 以优化性能。
5. 绝对布局 AbsoluteLayout
已废弃。通过 x/y 坐标精确放置控件,无法适配不同屏幕尺寸,不推荐使用。
6. 通用组件属性
| 属性 | 含义 |
|---|---|
android:layout_width |
宽度:match_parent(填满父容器)或 wrap_content(包裹内容)或具体 dp 值 |
android:layout_height |
高度,同上 |
android:id |
组件唯一标识 @+id/xxx |
android:padding |
内边距(控件内容到边框) |
android:layout_margin |
外边距(控件边框到相邻元素) |
android:gravity |
内容对齐方式 |
android:layout_gravity |
控件在父容器中的对齐方式 |
android:visibility |
visible / invisible(占位不可见) / gone(不占位) |
§5 控件与事件
1. 常用控件
| 控件 | 作用 |
|---|---|
| TextView | 显示文本,android:text="文本",android:textSize="16sp",android:textColor="#000" |
| Button | 按钮,继承自 TextView,常用 android:onClick="methodName" |
| EditText | 输入框,android:hint="请输入" 占位文字,android:inputType="textPassword" 输入类型 |
| ImageView | 显示图片,android:src="@drawable/ic_launcher",android:scaleType="centerCrop" |
| CheckBox | 复选框,isChecked() 判断勾选状态 |
| RadioButton | 单选按钮,放在 RadioGroup 中互斥 |
| Spinner | 下拉选择框,绑定 Adapter 设置选项 |
| ListView | 列表控件,通过 Adapter 绑定数据源,配合 setOnItemClickListener 处理点击 |
2. 事件处理方法
方式一:XML 中声明 onClick(最简单)
xml
<Button android:onClick="doLogin" />
java
public void doLogin(View view) {
// 在 Activity 中定义,方法名需与 XML 一致,参数固定为 View
}
方式二:匿名内部类 setOnClickListener
java
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 处理点击
}
});
方式三:Lambda(Java 8+ / Kotlin)
java
button.setOnClickListener(v -> { /* 处理点击 */ });
方式四:Activity 实现 View.OnClickListener 接口
java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
button.setOnClickListener(this);
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_login: // ...
}
}
}
3. dp / px / sp 单位
| 单位 | 含义 | 使用场景 |
|---|---|---|
| px | 像素点 | 不推荐写死,不同密度设备显示大小不同 |
| dp (dip) | 密度无关像素,1dp = 1px@160dpi | 布局宽高、间距,推荐 |
| sp | 比例无关像素,与 dp 类似但受系统字体大小设置影响 | 文字大小专用 |
换算:px = dp × (dpi / 160)
§6 菜单与对话框
1. 菜单类型与绘制
Android 标准三类菜单:
| 类型 | 触发方式 | 适用场景 |
|---|---|---|
| 选项菜单 OptionsMenu | 按 Menu 键或 ActionBar 三点图标 | 全局操作(设置、搜索) |
| 上下文菜单 ContextMenu | 长按某个 View | 针对特定控件的操作(删除、编辑) |
| 弹出菜单 PopupMenu | 点击触发 | 锚定到某个 View 弹出 |
选项菜单创建(重写两个方法):
java
// 1. 加载菜单布局
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu); // 从 XML 加载
return true;
}
// 2. 处理菜单点击
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_add: /* ... */ return true;
default: return super.onOptionsItemSelected(item);
}
}
菜单布局文件 res/menu/main_menu.xml:
xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_add" android:title="添加" android:icon="@drawable/ic_add" />
<item android:id="@+id/action_search" android:title="搜索" android:showAsAction="ifRoom" />
</menu>
2. Dialog / AlertDialog
创建 AlertDialog:
java
// 使用 Builder 模式
new AlertDialog.Builder(this)
.setTitle("提示") // 标题
.setMessage("确定删除吗?") // 内容
.setIcon(R.drawable.ic_warning) // 图标
.setPositiveButton("确定", (dialog, which) -> { // 确定按钮
// 执行删除
})
.setNegativeButton("取消", null) // 取消按钮
.setNeutralButton("稍后", null) // 中间按钮
.setCancelable(true) // 点击外部是否消失
.create()
.show();
关键点:
- 必须通过
Builder构造,不能直接new AlertDialog() setTitle设置标题,setMessage设置内容,setPositiveButton/NegativeButton/NeutralButton三个按钮- 调用
.show()才能显示
3. Toast 提示框
java
// 标准用法
Toast.makeText(context, "提示文字", Toast.LENGTH_SHORT).show();
// 参数说明
// 参数1: Context(Activity 中直接 this)
// 参数2: CharSequence 文字内容
// 参数3: 显示时长 Toast.LENGTH_SHORT(约2秒) 或 Toast.LENGTH_LONG(约3.5秒)
// 自定义位置
Toast toast = Toast.makeText(this, "居中提示", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
注意:必须调用 .show() 才显示!
§8 Android 消息机制
1. Message 与 Handler 定义
| 类 | 作用 |
|---|---|
| Handler | 消息处理器,负责发送 Message 到 MessageQueue 和在目标线程中处理 Message |
| Message | 消息载体,包含 what(int 标识)、arg1/arg2(int 参数)、obj(Object 数据) |
| MessageQueue | 消息队列,以单链表存储 Message,按时间排序 |
| Looper | 消息循环器,不断从 MessageQueue 中取 Message 分发给对应 Handler |
工作机制:
子线程 → Handler.sendMessage(msg) → MessageQueue.enqueueMessage()
↓
主线程 ← Looper.loop() 循环取出 ← handleMessage(msg)
2. 创建线程时的使用方法
java
// 步骤1: 在主线程创建 Handler
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 此方法运行在主线程,可安全更新 UI
switch (msg.what) {
case 1:
textView.setText((String) msg.obj);
break;
}
}
};
// 步骤2: 在子线程发送消息
new Thread(() -> {
// 模拟耗时操作
String data = fetchDataFromNetwork();
Message msg = Message.obtain(); // 推荐用 obtain() 复用,比 new 高效
msg.what = 1; // 消息标识
msg.obj = data; // 携带数据
handler.sendMessage(msg); // 发送到主线程处理
// 或使用 sendEmptyMessage(what) 发送空消息
// handler.sendEmptyMessage(2);
}).start();
Handler.post() 快捷方式:
java
new Thread(() -> {
String result = doHeavyWork();
handler.post(() -> textView.setText(result)); // 直接抛 Runnable 到主线程
}).start();
3. 线程通信 / 异步处理的含义
为什么需要 Handler?
- Android 规定:只有主线程(UI 线程)才能更新 UI 组件
- 子线程做网络请求、数据库查询等耗时操作,完成后通过 Handler 将结果抛回主线程更新 UI
这就是典型的"线程通信 / 异步处理"模式:子线程干活,主线程更新界面。
§9 网络编程
1. URL 相关基础
java
URL url = new URL("https://api.example.com/data?page=1");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET"); // 请求方式
conn.setConnectTimeout(5000); // 连接超时 5s
conn.setReadTimeout(5000); // 读取超时 5s
int code = conn.getResponseCode(); // 响应码 200/404/500
if (code == 200) {
InputStream is = conn.getInputStream();
// 读取流 → String
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String result = sb.toString();
}
conn.disconnect();
注意:网络请求必须放在子线程,Android 主线程禁止网络操作(NetworkOnMainThreadException)。
2. Socket 网络连接
java
// 客户端 Socket
Socket socket = new Socket("192.168.1.100", 8888); // IP + 端口
OutputStream out = socket.getOutputStream();
PrintWriter writer = new PrintWriter(out);
writer.println("Hello Server");
writer.flush();
InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String response = reader.readLine();
socket.close();
- Socket 是基于 TCP 的长连接,适合即时通讯等场景
- 与 HTTP 不同,Socket 可以双向实时通信
3. GET 与 POST 请求
| GET | POST | |
|---|---|---|
| 参数位置 | URL 后面 ?key=value&... |
请求体中 |
| 数据量 | 受 URL 长度限制(~2KB) | 无限制 |
| 安全性 | 参数暴露在 URL 中 | 相对安全 |
| 语义 | 获取数据 | 提交数据 |
GET 请求:
java
URL url = new URL("https://api.example.com/search?keyword=Android");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
POST 请求:
java
URL url = new URL("https://api.example.com/login");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true); // 允许输出
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 写入请求体
OutputStream os = conn.getOutputStream();
os.write("username=admin&password=123".getBytes());
os.flush();
os.close();
4. 获取服务端数据 / HTTP 请求完整流程
1. 创建 URL 对象(含地址和参数)
2. openConnection() 获取 HttpURLConnection
3. 设置请求方式(GET/POST)、超时、请求头
4. POST 需 setDoOutput(true) 并写入请求体
5. getResponseCode() 检查响应码
6. getInputStream() 读取响应数据
7. 在子线程中执行上述步骤,通过 Handler 将结果抛回主线程
8. 在 AndroidManifest.xml 中声明 <uses-permission android:name="android.permission.INTERNET" />
常见 HTTP 状态码: 200 OK、301 Moved、404 Not Found、500 Server Error
补充资料索引
| 资料 | 覆盖内容 |
|---|---|
| \[Android补充知识点] | res 目录细节、Intent 6 属性+Bundle、百分比布局、FrameLayout 前景、ImageButton/ToggleButton、EditText 补充、TabHost、ScrollView、RecyclerView、SubMenu、Toast 全方法、线程创建两种方式 |
| \[例题套卷6] | 补充知识点选择题+填空+简答+编程,侧重 RecyclerView、Bundle、FrameLayout |
| \[例题套卷7] | 补充知识点第二轮,侧重 百分比布局、TabHost、Toast 方法、RecyclerView vs ListView |