Android Activity生命周期与Intent传参实战指南
简介:本资源是一份面向软件学院本科生的《移动应用软件开发技术》课程实验报告,聚焦Android平台基础开发能力培养,适用于移动应用开发入门学习与实践复盘。报告系统覆盖Android开发环境搭建(JDK、Eclipse、SDK及ADT插件的安装、配置与验证)、Activity生命周期管理与Intent跳转机制、以及UI设计核心实践(TextView/Button/ImageView等组件与LinearLayout/RelativeLayout等布局器的应用),内容紧扣教学大纲,含详细操作步骤、截图要求与验证方法。资源为1个Word文档(.doc格式),完整记录4个核心实验全过程,文件大小1.63MB,结构清晰、图文指引明确,便于对照实操与课后复习。目前已有767人学习下载,是掌握Android开发入门流程、理解开发工具链协同关系、夯实Activity与UI双主线能力的实用型教学参考资料。
1. 这份 Android 移动应用开发实验报告,不是“过时的古董”,而是能直接复用的毕设/课设骨架
2013 年的实验报告?别急着划走——它恰恰是当前高校移动应用开发类课程最真实、最可落地的“教学锚点”。我带过三届软件学院本科生的移动开发课设,发现一个反直觉的事实:学生翻车最多的,从来不是 Kotlin 或 Jetpack Compose 的新语法,而是 Activity 生命周期没理清、Intent 传参漏判空、XML 布局嵌套层级失控导致 UI 错位。这份报告里埋着的,正是这些“血泪经验”的原始切片:从 JDK 6 + Eclipse + ADT 的经典组合,到startActivity()调用后onCreate()为何没触发、getExtras()返回 null 却不报错的玄学现场。它不教你怎么写高大上的跨平台框架,而是手把手带你把“按钮点一下跳页面、带参数过去、再显示出来”这个闭环跑通。适合两类人:一是正在赶 Android 课设 deadline 的本科生,需要一份结构完整、代码可粘贴、截图有依据、答辩能讲清原理的交付物;二是刚接手移动开发教学任务的青年教师,想快速拆解出一套可分阶段验收的实验模块。它解决的不是“未来趋势”,而是“今天下午三点前必须让模拟器跑起来”的刚需。
2. 环境搭建:不是照着官网点下一步,而是理解每个环节的职责边界与失效点
Android 开发环境搭建常被当成“安装教程”,但实际交付中,90% 的编译失败、AVD 启动黑屏、R 文件不生成问题,都源于对各组件职责边界的模糊。这份报告虽基于旧工具链(JDK 6 / Eclipse / ADT),但其模块划分逻辑至今有效:JDK 提供 Java 字节码运行时,Eclipse 是 IDE 容器,SDK 是 Android API 与工具集,ADT 是连接 IDE 与 SDK 的协议翻译层。下面按真实调试顺序展开关键配置与验证点。
2.1 JDK 6 环境变量:JAVA_HOME 必须指向 JDK 根目录,而非 JRE
很多学生将JAVA_HOME设为C:\Program Files\Java\jre7,导致javac命令不可用。正确路径应为 JDK 安装根目录(如C:\Program Files\Java\jdk1.6.0_45)。验证命令需在 CMD 中逐行执行:
# 检查 JAVA_HOME 是否生效 echo %JAVA_HOME% # 检查 java 和 javac 是否指向同一版本 java -version javac -version # 编译并运行测试文件(注意:test.java 必须含 public class) echo "public class test { public static void main(String[] args) { System.out.println(\"JDK OK\"); } }" > test.java javac test.java java test提示:若
javac报“不是内部或外部命令”,说明PATH未包含%JAVA_HOME%\bin;若java -version与javac -version版本号不一致,说明系统 PATH 中存在其他 Java 路径干扰,需清理。
2.2 Eclipse 解压即用的本质:workspace 与 plugin 目录分离设计
Eclipse 不是传统安装程序,其核心在于 workspace(工作区)与 installation(安装目录)物理隔离。这意味着:
- 同一 Eclipse 安装目录可被多个 workspace 复用(如
D:\eclipse\下建workspace_android和workspace_javaee); - ADT 插件安装后存于
eclipse\plugins\子目录,而非注册表; - 若 Eclipse 启动报
Plugin org.eclipse.core.runtime was unable to load...,大概率是 workspace 元数据损坏,不要重装 Eclipse,只需新建 workspace 并重新导入项目。
验证方式:启动 Eclipse →File → Switch Workspace → Other...→ 新建路径(如D:\workspace_android)→ 重启后检查Window → Preferences → General → Workspace显示路径是否更新。
2.3 SDK 离线安装:platforms 与 tools 的版本耦合关系是黑匣子
在线 SDK Manager 已淘汰,但离线安装逻辑仍具指导意义。关键点在于:tools(如adb.exe,aapt.exe)与platforms\android-XX(如android-2.2)必须版本兼容。例如tools_r06仅支持android-1.5至android-2.2,若强行放入android-4.0平台,aapt会报Invalid resource directory name。离线安装步骤需严格遵循:
- 解压
android-sdk_r16-windows.zip到固定路径(如D:\android-sdk); - 手动创建必需空目录:
platforms,platform-tools,tools,add-ons,samples,docs; - 下载指定 URL 的 ZIP 包(如
android-2.2_r01-windows.zip),解压时必须保留 ZIP 内原始目录结构(即解压后得到android-2.2文件夹,再将其整体移入D:\android-sdk\platforms\); - 将
tools_r06-windows.zip解压内容覆盖至D:\android-sdk\tools\。
验证命令:
# 进入 SDK tools 目录 cd /d D:\android-sdk\tools # 检查 adb 是否识别设备(需先开 AVD 或连真机) adb version adb devices # 检查 aapt 是否能解析 layout XML(取任意 activity_main.xml 测试) aapt dump badging D:\workspace\MyApp\res\layout\activity_main.xml 2>nul && echo "aapt OK" || echo "aapt broken"2.4 ADT 插件安装:URI 协议与证书信任的隐性依赖
http://dl-ssl.google.com/android/eclipse/这个 URI 看似普通,实则暗含两个关键约束:
dl-ssl表示强制 HTTPS,若本地网络拦截 SSL 证书(如企业防火墙),Eclipse 会静默失败,界面无报错;eclipse/路径下必须存在content.jar和artifacts.jar,否则插件列表为空。
绕过方案(当网络受限时):
- 从可信镜像站下载
adt-bundle-windows-x86_64-2013xxxx.zip(含预装 ADT 的 Eclipse); - 或手动下载
ADT-23.0.7.zip,解压后将features/与plugins/目录内容复制到 Eclipse 对应目录,再通过Help → Install New Software → Add → Local加载本地路径。
验证成功标志:重启 Eclipse 后,菜单栏出现Window → Android SDK Manager和Window → AVD Manager,且Project → Properties → Android可选中已安装的 Target Platform。
3. Activity 实战:从生命周期切入,把 Intent 传参做成可验证的确定性流程
Activity 不是“页面”,而是具备明确状态机的组件。实验二的两段代码看似简单,却暴露了学生对onCreate()触发时机、Intent数据载体本质、Bundle序列化边界的普遍误解。我们以TestActivity02为例,重构为可调试、可断点、可验证的工程实践。
3.1 MainActivity 启动逻辑:显式 Intent 的构造必须绑定目标 Activity 类名
原代码中testintent.setClass(TextMainActivity.this,test_2.class)是正确写法,但易被误写为setClassName()或setAction()。关键区别在于:
setClass(Context, Class):直接指定目标 Activity 类,适用于同一应用内跳转;setClassName(String, String):需传入包名+类名字符串,易因拼写错误崩溃;setAction(String):用于隐式 Intent,需在AndroidManifest.xml中声明<intent-filter>。
加固写法(增加空指针防护与日志):
// TextMainActivity.java y.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 1. 构造 Bundle 并校验数据 Bundle bundle = new Bundle(); String data = "中国"; if (data != null && !data.trim().isEmpty()) { bundle.putString("name", data); } else { Log.w("MainActivity", "Attempted to pass null/empty data"); return; } // 2. 构造 Intent 并显式指定目标类 Intent intent = new Intent(TextMainActivity.this, test_2.class); intent.putExtras(bundle); // 3. 添加调试标记(便于 Logcat 过滤) intent.putExtra("debug_source", "TextMainActivity"); // 4. 启动并检查是否成功 try { startActivity(intent); Log.d("MainActivity", "Intent sent to test_2 successfully"); } catch (ActivityNotFoundException e) { Log.e("MainActivity", "Target Activity not found: " + e.getMessage()); Toast.makeText(TextMainActivity.this, "目标页面未找到", Toast.LENGTH_SHORT).show(); } } });3.2 test_2 接收逻辑:Bundle 解包必须前置非空判断,避免 Crash
原代码Bundle tbd = this.getIntent().getExtras();未校验getIntent()和getExtras()返回值,一旦startActivity()被异常中断(如内存不足杀进程),tbd为 null,后续tbd.getString("name")直接抛NullPointerException。标准防御式写法:
// test_2.java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second); TextView test = (TextView) findViewById(R.id.ruirui); // 1. 获取 Intent 并校验 Intent intent = getIntent(); if (intent == null) { Log.e("test_2", "Received null Intent"); test.setText("Error: Null Intent"); return; } // 2. 获取 Bundle 并校验 Bundle extras = intent.getExtras(); if (extras == null) { Log.w("test_2", "Intent has no extras"); test.setText("No data received"); return; } // 3. 安全提取字符串(提供默认值) String name = extras.getString("name", "Default Name"); if (name == null) { Log.w("test_2", "Key 'name' exists but value is null"); name = "Null Value"; } test.setText(name); Log.d("test_2", "Displaying name: " + name); }3.3 生命周期可视化:用 Logcat 验证 Activity 状态流转
仅靠界面截图无法证明onCreate()正常执行。必须在Logcat中观察生命周期方法调用序列。在test_2中添加完整生命周期日志:
// test_2.java(补充) @Override protected void onStart() { super.onStart(); Log.d("test_2", "onStart called"); } @Override protected void onResume() { super.onResume(); Log.d("test_2", "onResume called"); } @Override protected void onPause() { super.onPause(); Log.d("test_2", "onPause called"); } @Override protected void onStop() { super.onStop(); Log.d("test_2", "onStop called"); } @Override protected void onDestroy() { super.onDestroy(); Log.d("test_2", "onDestroy called"); }预期 Logcat 输出(过滤test_2):
D/test_2: onCreate called D/test_2: onStart called D/test_2: onResume called若只看到onCreate无后续,说明 Activity 被异常终止(如AndroidManifest.xml中未声明该 Activity);若返回时无onPause/onStop,说明用户未真正离开页面(如弹出 Dialog)。
3.4 AndroidManifest.xml 的隐性约束:Activity 声明缺失是静默失败主因
学生常忽略AndroidManifest.xml中 Activity 的<activity>声明。即使 Java 类和 Layout 存在,未声明则startActivity()会抛ActivityNotFoundException。正确声明格式:
<!-- AndroidManifest.xml --> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <!-- 主 Activity 必须含 LAUNCHER --> <activity android:name=".TextMainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 被启动的 Activity 必须声明,但无需 intent-filter --> <activity android:name=".test_2" android:label="Second Activity" /> </application>注意:
android:name值必须与 Java 类名完全匹配(包括大小写),.test_2表示com.example.test.test_2(包名前缀由<manifest package="com.example.test">定义)。
4. UI 设计实战:用 LinearLayout 嵌套规则破解“布局错乱”的玄学问题
实验三的 UI 设计看似是拖控件,实则是理解 Android 布局引擎计算逻辑的入口。图 3.1 的三层嵌套(Vertical LinearLayout → Horizontal LinearLayout → TableLayout)暴露出学生对layout_weight、layout_height、gravity三者作用域的混淆。我们以“四色块横向布局”为例,给出可复现的 XML 结构与调试方法。
4.1 四色块布局:weight 分配必须配合 0dp 高度/宽度
原 XML 中<TextView android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_weight="1" />存在致命错误:fill_parent(已废弃)应为match_parent,且当使用layout_weight时,对应方向尺寸必须设为0dp。否则 weight 计算失效,导致色块宽度不均。
修正后的 activity_main.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="match_parent" android:orientation="vertical"> <!-- 外层 Vertical LinearLayout:占满屏幕 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" <!-- 占垂直空间 2 份 --> android:orientation="horizontal"> <!-- 四个色块:每个 width=0dp + weight=1,均分水平空间 --> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:background="#CE0000" android:text="red" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:background="#00A600" android:text="green" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:background="#0000CE" android:text="blue" /> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:background="#CECE00" android:text="yellow" /> </LinearLayout> <!-- TableLayout:占垂直空间 1 份 --> <TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:stretchColumns="*"> <TableRow> <TextView android:text="Row1-Col1" /> <TextView android:text="Row1-Col2" /> <TextView android:text="Row1-Col3" /> </TableRow> <TableRow> <TextView android:text="Row2-Col1" /> <TextView android:text="Row2-Col2" /> <TextView android:text="Row2-Col3" /> </TableRow> <TableRow> <TextView android:text="Row3-Col1" /> <TextView android:text="Row3-Col2" /> <TextView android:text="Row3-Col3" /> </TableRow> </TableLayout> <!-- 底部 Vertical LinearLayout:占垂直空间 1 份 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="center" android:background="#FF6B6B" android:text="Line1" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="center" android:background="#4ECDC4" android:text="Line2" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="center" android:background="#FFBE0B" android:text="Line3" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:gravity="center" android:background="#FB5607" android:text="Line4" /> </LinearLayout> </LinearLayout>4.2 多输入对话框:EditText 输入验证与 Toast 输出的原子性保障
图 3.2 要求“点击按钮后输出”,但原描述未明确输出位置。实践中需同时满足:
Toast显示用户可见反馈;TextView更新界面状态;Logcat记录结构化日志供调试。
activity_text_main.xml(精简版):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="用户名:" /> <EditText android:id="@+id/edit_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="密码:" /> <EditText android:id="@+id/edit_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:hint="请输入密码" /> <Button android:id="@+id/btn_submit" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="提交" /> <TextView android:id="@+id/tv_result" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="结果将显示在此处" /> </LinearLayout>TextMainActivity.java(关键逻辑):
// TextMainActivity.java(续) private EditText editUsername; private EditText editPassword; private TextView tvResult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_text_main); editUsername = (EditText) findViewById(R.id.edit_username); editPassword = (EditText) findViewById(R.id.edit_password); tvResult = (TextView) findViewById(R.id.tv_result); Button btnSubmit = (Button) findViewById(R.id.btn_submit); btnSubmit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 1. 获取输入并校验(空值、长度) String username = editUsername.getText().toString().trim(); String password = editPassword.getText().toString().trim(); if (username.isEmpty() || password.isEmpty()) { Toast.makeText(TextMainActivity.this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show(); return; } if (username.length() < 3 || password.length() < 6) { Toast.makeText(TextMainActivity.this, "用户名至少3位,密码至少6位", Toast.LENGTH_SHORT).show(); return; } // 2. 组装输出字符串 String result = String.format("提交成功!用户名:%s,密码长度:%d", username, password.length()); // 3. 三端同步输出 tvResult.setText(result); Toast.makeText(TextMainActivity.this, result, Toast.LENGTH_LONG).show(); Log.i("TextMainActivity", "Form submitted: " + result); } }); }4.3 RelativeLayout 与 LinearLayout 的选择哲学:何时用哪个?
学生常问“为什么不用 RelativeLayout 替代所有 LinearLayout?”答案在于性能与可维护性权衡:
- LinearLayout:适合线性排列(单行/单列),
weight分配直观,嵌套过深(>3 层)时渲染性能下降; - RelativeLayout:适合相对定位(如“按钮在文本框右侧”),减少嵌套层级,但属性间存在隐式依赖(如
android:layout_toRightOf需要被参照 View 已定义),调试困难; - 最佳实践:外层用
LinearLayout划分大区块(Header/Content/Footer),区块内用RelativeLayout精确定位控件。图 3.1 的三层结构正是此思想的体现。
5. 常见问题排查:Activity 启动失败、UI 错位、R 文件不生成的 5 个硬核解法
这份实验报告交付过程中,我见过太多学生卡在同一个地方反复折腾。以下是五个最高频、最易被忽略的“翻车点”,按现象→原因→解决三步法给出可立即执行的方案。
5.1 现象:点击按钮无反应,Logcat 无任何日志,onClick()方法未进入
原因:Button的OnClickListener未正确绑定,或findViewById()返回 null(ID 名与 XML 不匹配)
解决:
- 在
onCreate()中findViewById()后立即加空指针判断:Button b = (Button) findViewById(R.id.button1); if (b == null) { Log.e("MainActivity", "Button with id 'button1' not found in layout"); return; } b.setOnClickListener(...); - 检查
activity_main.xml中Button的android:id是否为@+id/button1(+表示创建新 ID,漏写则引用不存在的 ID); - 清理项目:
Project → Clean → Clean all projects,强制重建 R.java。
5.2 现象:Activity 跳转后黑屏或闪退,Logcat 报ClassNotFoundException
原因:AndroidManifest.xml中未声明目标 Activity,或android:name拼写错误(大小写敏感)
解决:
- 打开
AndroidManifest.xml,确认<activity android:name=".test_2">存在; - 检查
test_2.java的包声明(如package com.example.test;)与android:name前缀是否一致(.test_2表示com.example.test.test_2); - 在
Logcat中过滤AndroidRuntime,查看完整异常栈,定位具体类名。
5.3 现象:XML 布局中TextView文字不显示,或背景色无效
原因:android:text值为@string/my_activity,但res/values/strings.xml中未定义该 string
解决:
- 打开
strings.xml,添加:<string name="my_activity">my_activity</string> - 若使用硬编码文字(如
android:text="my_activity"),确保无中文全角符号(如引号、空格); - 检查
TextView的android:layout_height是否为0dp且未设weight,导致高度为 0。
5.4 现象:R.java文件不生成,R.id.button1报红
原因:XML 文件存在语法错误(如未闭合标签、非法字符),或资源文件名含大写字母/特殊符号
解决:
- 查看
Problems视图,定位具体 XML 错误行; - 检查
res/下所有文件名:只能小写字母、数字、下划线(如activity_main.xml✅,ActivityMain.xml❌); - 删除
gen/目录(Eclipse 自动重建),或Project → Build Automatically开启自动构建。
5.5 现象:AVD 启动缓慢,或模拟器窗口空白
原因:SDK Tools 版本与 AVD 系统镜像不兼容,或宿主机未开启硬件加速(Intel HAXM / AMD Hypervisor)
解决:
- 在
SDK Manager中,确保Tools → Android SDK Tools与System Images → Android 2.2 (API 8)同期下载(r16 对应 2.2); - 检查 BIOS 中 Virtualization Technology (VT-x) 是否启用;
- 手动安装 HAXM:下载
intelhaxm-android.exe,运行安装,重启电脑。
6. 验收与答辩:用三张表、一次真机测试、一个调试习惯拿下满分
交报告不等于完成,验收和答辩才是检验你是否真正吃透这套方案的关键。我带过的某高校软件学院课程,最终成绩 40% 来自实验报告文档,60% 来自现场演示与问答。以下是我总结的“三张表+一次测试+一个习惯”通关法,助你避开答辩雷区。
6.1 验收三张表:让老师一眼看懂你的工作量与思考深度
很多学生只交代码和截图,老师无法快速评估工作质量。我要求学生必须附上三张结构化表格,它们不是形式主义,而是你技术思维的具象化。
表 1:环境配置验证清单(自证搭建成功)
| 检查项 | 验证命令/操作 | 预期输出 | 实际截图页码 | 是否通过 |
|---|---|---|---|---|
| JDK 安装 | java -version&javac -version | 显示 1.6.x | P3 | ✓ |
| Eclipse ADT | Window → Android SDK Manager可打开 | 显示已安装 platforms | P5 | ✓ |
| SDK Tools | D:\android-sdk\tools\adb version | 显示 r16 | P7 | ✓ |
| AVD 运行 | 启动名为Android_2.2的 AVD | 模拟器显示 Android 启动动画 | P9 | ✓ |
设计说明:这张表强迫你把“安装完成”转化为可验证的动作。老师只需扫一眼“是否通过”列,就能确认环境真实性,避免“截图是网上找的”质疑。
表 2:Activity 通信测试用例表(证明 Intent 逻辑健壮)
| 测试场景 | 操作步骤 | 预期结果 | 实际结果 | Logcat 关键日志(过滤 test_2) | 是否通过 |
|---|---|---|---|---|---|
| 正常传参 | MainActivity 点按钮 | test_2 显示“中国” | 显示“中国” | D/test_2: Displaying name: 中国 | ✓ |
| 空字符串 | 修改 MainActivity 传"" | test_2 显示“Default Name” | 显示“Default Name” | D/test_2: Displaying name: Default Name | ✓ |
| null 参数 | 注释bundle.putString()行 | test_2 显示“No data received” | 显示“No data received” | W/test_2: Intent has no extras | ✓ |
设计说明:这张表把“功能实现”升级为“质量保障”。它证明你不仅会写代码,更懂如何设计边界测试。答辩时老师若问“如果用户不输内容怎么办?”,你可直接指向此表第三行。
表 3:UI 布局响应性测试表(验证适配能力)
| 设备类型 | 模拟器配置 | 截图关键特征 | 是否符合设计图 3.1 | 备注 |
|---|---|---|---|---|
| HVGA (320x480) | AVD: Android 2.2, HVGA | 四色块等宽,TableLayout 三行三列清晰 | ✓ | 无截断 |
| WVGA800 (480x800) | AVD: Android 2.2, WVGA800 | 底部四行 TextView 高度均等 | ✓ | 无重叠 |
| 平板 (1024x600) | AVD: Android 2.2, WXGA | 外层 Vertical LinearLayout 占满屏幕 | ✓ | 无留白 |
设计说明:移动端核心是适配。此表用不同分辨率验证
layout_weight和match_parent的实际效果,比单纯说“我用了相对布局”有力得多。
6.2 一次真机测试:用手机拍视频比截图更有说服力
截图可以伪造,但真机操作视频无法。我要求学生必须用手机录制一段 60 秒内的操作视频:
- 前 10 秒:展示手机型号(如“HTC Desire Z, Android 2.2”);
- 中间 30 秒:从 MainActivity 点击按钮 → 进入 test_2 页面 → 返回 → 再次点击 → 输入“中国” → 显示正确;
- 后 20 秒:横竖屏切换,展示 UI 自适应(若布局支持)。
视频命名规范:学号_姓名_ActivityTest.mp4(如2013001_张三_ActivityTest.mp4)。
交付方式:将视频上传至云盘,报告末尾附链接(设置为“任何人可查看”)。
为什么有效:视频包含时间戳、设备信息、操作连贯性,彻底杜绝“P 图造假”嫌疑。某次答辩中,一位同学因视频里 AVD 启动时间长达 90 秒,被老师追问优化方案,反而展示了他对
emulator -accel on命令的掌握,拿了加分。
6.3 一个调试习惯:Logcat 过滤器必须带模块标签
学生常犯的错误是Log.d("msg", "..."),导致 Logcat 信息淹没。我的铁律是:所有 Log 必须用类名或模块名作为 tag,且在 Logcat 视图中创建永久过滤器。
操作步骤:
- 在 Eclipse 中打开
Logcat视图; - 点击右上角
+按钮 →Filter Settings; - Filter Name 填
MainActivity,by Log Tag 填MainActivity; - 同样创建
test_2、UI_Test过滤器。
答辩话术:
“老师,我所有的调试都基于 Logcat 过滤。比如您想看 Activity 跳转过程,只需点这个
test_2过滤器,就能看到完整的onCreate→onStart→onResume日志链,以及传入的数据值。这比截图更能证明逻辑正确性。”
从那以后我每次带新学生做移动开发实验,都强制他们在第一天就配置好这三个过滤器,并把Log.d(TAG, ...)写进所有 Activity 的onCreate()。因为真正的工程能力,不在于写出能跑的代码,而在于写出可验证、可追溯、可解释的代码。希望帮到你。
本文还有配套的精品资源,点击获取