☰
中职移动应用与开发赛项备赛指南:从赛题拆解到Android工程实践
2026/10/12 14:55:17 网站建设 项目流程

简介:2023年全国职业院校技能大赛中职移动应用与开发赛项赛题,是一份面向中职组选手及指导教师的官方赛题文档,适合备赛训练、赛制研读与模拟评分。赛题以“数字生活”为主题,围绕智慧党建、乡村民宿、智慧健康等融合场景展开,模块A要求使用Adobe XD完成看电影、物流查询、找工作、宠物医院等界面的高保真原型图,模块B基于Android Studio或HbuilderX开发“时代楷模”App,覆盖UI还原、网络通信、数据解析、数据存储与打包发布,模块C则考核产品使用手册和缺陷分析文档的提交质量,并明确了各模块分值、竞赛时间、成果物命名规范、提交路径以及禁止填写选手信息的注意事项。资源为1个PDF文件,压缩包大小2.55MB,已有945人学习;研读后可快速梳理国赛考核逻辑,判断自身在原型设计、前端编码、测试交付等环节的薄弱点,并依照官方任务要求开展仿真训练,是一份适合中职移动应用赛项备赛的参考材料。

1. 2023 年的中职移动应用与开发赛项,赛题究竟在考什么

很多第一次带队的老师看到赛题压缩包时,第一反应是“这不就是现场写个 App 吗”。真正开始做才发现,2023 年的中职移动应用与开发赛项更像一场“限时还原工程”:拿到原型图、切图和 JSON 数据文件,在规定时间里把页面搭出来、把交互跑通、把接口接上,最后还要把工程打包提交到评分环境。评分的人不会关心你的动画有多炫,只会按任务书里的操作步骤逐一点击,点不到就算丢分。

这个方向适合两类人:一类是正在备赛的中职学生,需要知道先练什么、赛场上哪些地方最容易卡住;另一类是指导老师,想快速判断训练计划该往哪个模块倾斜。赛题表面上考代码,实际上考的是对任务书的拆解能力、对素材目录的理解,以及“在有限时间内先保住核心流程”的工程判断力。下面按我帮某中职学校备赛时的思路,把这套赛题从前到后拆一遍,附带可直接套用的代码和避坑记录。

2. 赛题结构和评分逻辑:先判断裁判手里拿的是哪张表

2.1 赛题包的常见内容和工作流程

中职移动应用与开发赛项通常会把所有材料打成一个压缩包,解压后大约包含五类东西:任务书、素材目录、接口说明、原型图、评分标准节选。任务书会写清楚需要实现几个页面、每个页面的功能边界、最低支持的 Android 版本;素材目录一般分成res、assets、icon等子目录,把切图、占位图、JSON 数据都放在里面。接题后的前 10 分钟,别急着打开 Android Studio,先把压缩包里的目录结构、文件命名和接口字段看一遍。这个习惯能避免后面反复回去翻素材。

我一般会让队员按下面的顺序过一遍材料:先读任务书,圈出“必须实现”和“加分项”;再打开原型图,对照任务书列出页面清单;最后打开 JSON 数据文件,确认字段名和类型。这里有个容易被忽略的地方——任务书里可能要求“点击列表项跳转到详情页”,但原型图上详情页的字段可能比 JSON 数据多,这时候要优先以任务书为准,不要脑补字段。赛题给的 JSON 数据,字段名往往和实体类一一对应,拼错一个下划线就会在评分时暴露。

2.2 评分点拆解:功能完整、交互还原、代码规范

从历年的出题方向看,评分表大约分成四块:功能完整度、界面还原度、异常处理、代码规范。功能完整度占比最大,包括登录、列表、详情、收藏、个人中心这类常规模块;界面还原度看的是字体大小、间距、圆角、背景色是否和原型图接近;异常处理考的是接口失败时有没有提示、没网时页面会不会白屏;代码规范体现在类名、包名、资源文件命名和关键注释。

这里有一个很现实的优先级:功能跑通 > 界面接近 > 异常处理 > 代码注释。很多学生喜欢先花 40 分钟抠一个列表项的阴影效果,最后发现登录请求还没接上,这是典型的备赛误区。正确做法是先把所有页面的核心跳转跑通,再回头做视觉精调。评分环境通常是模拟器或真机直接操作,只要界面能用、不会闪退,界面还原度不会扣太多分;反过来,如果某个按钮点击没有响应,整道功能题可能一分没有。

2.3 三到四小时的时间分配方案

2023 年的赛题时长一般是 3 到 4 个小时,具体以任务书为准。我带队训练时常用一个“30+90+40+30+20”的时间模型:前 30 分钟读题、列页面清单、建工程;中间 90 分钟写页面和功能;再花 40 分钟接接口和 Mock 联调;留 30 分钟做自测和打包;最后 20 分钟检查提交内容。这个模型不适合所有人,但它的核心逻辑是:把“打包前至少留 50 分钟检查”设为硬性要求,而不是把时间全花在写代码上。

如果赛题只要求做两个模块,时间分配可以更激进,比如只留 15 分钟读题,把多出来的时间放在自测上。自测时不要只测正常路径,还要测“输入框为空时点登录”“断网时打开列表”这类边界场景。评分人员有时会刻意点这些按钮,目的是看你有没有做异常处理。哪怕只是弹一个 Toast,也比无反应强得多,因为无反应会被直接判定为功能缺失。

3. 按赛题模块复现:Android 工程从零到闭环

3.1 建空工程和资源目录规划

打开 Android Studio 后,建议选择 Empty Activity 模板,而不是带 BottomNavigation 或 DrawerLayout 的模板,因为自带模板会生成多余的界面和依赖,反而干扰赛题要求。项目参数上,我一般会把 Package name 设置为com.school.app这样的简短域名,避免包名过长导致资源引用路径出错。Minimum SDK 选择 API 23,这样能覆盖大多数中职学校机房里的测试机;Target SDK 选 API 30 或 32,主要目的是避免 Android 系统高版本对明文网络请求的限制。

赛题给的素材通常需要手动拷贝到工程目录,下面是一个常见的初始化命令:

# 解压赛题素材包后,在项目根目录执行 # 先把 JSON 数据文件放到 assets 目录 mkdir -p app/src/main/assets/mock cp -r 赛题素材包/json/* app/src/main/assets/mock/ # 把切好的图片放到 drawable 目录,注意目录名不能写错 mkdir -p app/src/main/res/drawable/ cp -r 赛题素材包/images/* app/src/main/res/drawable/

这段命令会创建assets/mock目录,把 JSON 文件复制进去,再把切图复制到drawable。后续代码里访问 assets 文件时,路径要以mock/xxx.json开头;访问图片时,直接在布局里用@drawable/xxx引用。这里要注意一点:res/drawable目录下不能出现文件名大小写混用的情况,比如IMG_Logo.png编译时会直接报资源名错误。Android 系统的资源命名规则是只能用小写字母、数字和下划线,养成习惯后才不会在提交前突然冒出一堆编译错误。

3.2 登录页与表单校验

登录页是赛题中出现频率最高的入口,因为它能串联起“输入账号密码 → 请求接口 → 保存 Token → 跳转主页”这条完整链路。实现登录页时,我建议先写一个LoginActivity,把表单校验和网络请求分开,这样评分人员如果快速点击多次登录按钮,不会出现重复请求叠加的问题。下面是一个可以直接套用的登录页核心代码:

// LoginActivity.java 关键部分 public class LoginActivity extends AppCompatActivity { private EditText etAccount; private EditText etPassword; private Button btnLogin; private ProgressBar loading; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); etAccount = findViewById(R.id.et_account); etPassword = findViewById(R.id.et_password); btnLogin = findViewById(R.id.btn_login); loading = findViewById(R.id.loading); btnLogin.setOnClickListener(v -> doLogin()); } private void doLogin() { String account = etAccount.getText().toString().trim(); String password = etPassword.getText().toString().trim(); // 先做本地非空校验,避免无效请求 if (account.isEmpty() || password.isEmpty()) { Toast.makeText(this, "账号和密码不能为空", Toast.LENGTH_SHORT).show(); return; } loading.setVisibility(View.VISIBLE); // requestLogin 是下面的网络请求方法,具体实现见第4章 Mock 联调 requestLogin(account, password); } }

这段代码的核心作用是:点击登录按钮后,先取输入框内容并去除首尾空格,再判断是否为空,空值直接拦截并提示。这样做的原因是评分环境可能没有后端服务,如果什么都没输入就发请求,最后只会得到超时错误,白白浪费检查时间。登录按钮点击后显示加载框,防止用户重复点击;加载框的显示和隐藏要放在请求回调里,否则请求失败时加载框会一直卡在界面上。网络请求的方法名requestLogin可以自行封装,但建议保持接口路径和参数名跟赛题任务书完全一致,因为评分环境可能会对接口路径做强匹配。

3.3 列表页与详情页:用 RecyclerView 支撑核心流程

中职移动应用与开发赛项很喜欢考“首页列表 + 点击进详情”的组合,因为它能同时考察数据展示、图片加载、页面跳转和空状态处理。列表页最推荐的控件是 RecyclerView,配合一个简单的 ListAdapter 就能满足赛题要求,不需要引入复杂框架。下面是一个常见的 Adapter 写法:

// ListAdapter.java 列表适配器 public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> { private List<NewsBean> dataList = new ArrayList<>(); public void setData(List<NewsBean> list) { dataList.clear(); dataList.addAll(list); notifyDataSetChanged(); } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_news, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { NewsBean bean = dataList.get(position); holder.tvTitle.setText(bean.getTitle()); holder.tvSummary.setText(bean.getSummary()); // 用 placeholder 兜底,避免图片加载失败导致整个 item 显示空白 Glide.with(holder.itemView.getContext()) .load(bean.getCoverUrl()) .placeholder(R.drawable.ic_placeholder) .error(R.drawable.ic_error) .into(holder.ivCover); } static class ViewHolder extends RecyclerView.ViewHolder { TextView tvTitle; TextView tvSummary; ImageView ivCover; ViewHolder(View itemView) { super(itemView); tvTitle = itemView.findViewById(R.id.tv_title); tvSummary = itemView.findViewById(R.id.tv_summary); ivCover = itemView.findViewById(R.id.iv_cover); } } }

Adapter 的核心是setData方法,它清空旧数据并加入新数据后调用notifyDataSetChanged刷新列表。注意这里必须调用notifyDataSetChanged,否则 RecyclerView 不会重新绘制。onCreateViewHolder只负责创建布局实例,onBindViewHolder负责绑定数据,两者职责不能混。图片加载使用 Glide 时,placeholder和error两个参数建议都写上,赛题给的图片地址有时是相对路径,加载失败时至少能看到一个占位图,而不是一个空白方块。

详情页通常接收列表项传递的 id 或标题参数,最简单的方式是 Intent 传值。跳转代码可以写在列表点击事件里,比如:

// 在 Activity 中给 RecyclerView 设置 item 点击事件 adapter.setOnItemClickListener((position, bean) -> { Intent intent = new Intent(ListActivity.this, DetailActivity.class); intent.putExtra("id", bean.getId()); intent.putExtra("title", bean.getTitle()); startActivity(intent); });

接收端在DetailActivity中用getIntent().getStringExtra("id")取出来,再根据这个 id 去请求详情接口或从本地缓存读取。赛题有时会让详情页展示多条数据,这时要注意 id 是 String 类型还是 int 类型,从 JSON 里解析时保持一致,否则用equals判断时容易出现1和"1"不匹配的怪问题。

3.4 本地缓存与登录态保持

赛题评分时,评分人员可能在同一个 App 里反复登录退出,甚至杀掉进程重新打开。如果每次冷启动都要求重新登录,不一定算功能缺失,但如果你能在重新打开后保持登录态,通常会被视为加分项。最简单的方案是使用 SharedPreferences 保存 Token 和用户信息,而列表数据可以用 JSON 字符串缓存到本地,下次启动时先显示缓存再刷新网络。下面是一个轻量级缓存工具类:

// CacheManager.java 本地缓存工具 public class CacheManager { private static SharedPreferences sp; // 在 Application 或第一个 Activity 中调用 init public static void init(Context context) { sp = context.getSharedPreferences("app_cache", Context.MODE_PRIVATE); } public static void saveString(String key, String value) { sp.edit().putString(key, value).apply(); } public static String getString(String key) { return sp.getString(key, ""); } public static void clearLogin() { sp.edit().remove("token").apply(); } }

这个工具类用apply()写入数据,它是异步提交,不会阻塞 UI 线程,比commit()更适合在界面操作中调用。登录成功以后执行CacheManager.saveString("token", token),后续请求列表时带上这个 token;退出登录时执行clearLogin()。列表数据的缓存方式同理,把接口返回的整个数组转成字符串存进去,读取时再用JSONArray解析回对象列表。这样做的另一个好处是,就算评分环境完全断网,App 也不是黑匣子,至少能显示上一批数据,避免白屏。

需要特别注意:SharedPreferences 不适合存体积很大的数据,只适合放 Token、用户信息和少量列表缓存。如果赛题要求本地收藏几十条记录,可以用 SQLite,但为了节约时间,我建议先直接拖一个 JSON 字符串到 SharedPreferences 顶住,等核心流程跑通后再考虑换数据库。

4. 接口联调与数据模拟:没有后端时怎么跑通评分流程

4.1 用本地 JSON 文件模拟后端接口

正式比赛时,赛题通常会提供一个后端接口地址或要求考生自己搭 Mock。但实际训练中,很多中职学校没有现成后端,于是就会遇到“页面写完了,接口怎么都调不通”的尴尬。我一般会在工程里放一个MockInterceptor,用本地 JSON 文件模拟接口响应,这样既能调试 UI,也能保证评分环境在没有网络的情况下也能跑通。先看assets/mock/login.json的格式:

{ "code": 0, "message": "success", "data": { "token": "mock_token_a1b2c3", "userInfo": { "userName": "student01", "displayName": "赛题演示用户" } } }

这个 JSON 结构遵循了常见的“code + message + data”三层结构,code=0表示成功,非 0 表示业务失败。接下来用 OkHttp 的 Interceptor 拦截指定路径,直接返回这个字符串。下面是MockInterceptor的完整写法:

// MockInterceptor.java 本地模拟接口 public class MockInterceptor implements Interceptor { private Context context; public MockInterceptor(Context context) { this.context = context; } @Override public Response intercept(Chain chain) throws IOException { String path = chain.request().url().encodedPath(); if ("/api/login".equals(path)) { return buildJsonResponse(chain, loadMockFile("login.json")); } if ("/api/news/list".equals(path)) { return buildJsonResponse(chain, loadMockFile("list.json")); } if ("/api/news/detail".equals(path)) { return buildJsonResponse(chain, loadMockFile("detail.json")); } return chain.proceed(chain.request()); } private String loadMockFile(String fileName) throws IOException { InputStream is = context.getAssets().open("mock/" + fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) != -1) { baos.write(buffer, 0, len); } is.close(); return baos.toString("UTF-8"); } private Response buildJsonResponse(Chain chain, String json) { ResponseBody body = ResponseBody.create( MediaType.parse("application/json; charset=utf-8"), json); return new Response.Builder() .code(200) .message("OK") .body(body) .request(chain.request()) .protocol(Protocol.HTTP_1_1) .build(); } }

这段代码的核心机制是:通过encodedPath()获取请求 URL 里的路径,比如http://123.456.789.10/api/login对应/api/login,命中后直接读取本地 JSON 并构造一个 HTTP 200 响应。这样做的好处是,不管真实后端在不在线,App 的前端逻辑都能完整跑一遍。

在使用这个 Interceptor 时要注意两个参数:第一个是context.getAssets().open("mock/" + fileName)中的路径前缀,如果你的 JSON 文件直接放在 assets 根目录,这里就要去掉mock/前缀,保持一致;第二个是MediaType.parse("application/json; charset=utf-8")不要省略 charset,否则中文可能显示成乱码。正式提交赛题时,如果评分环境允许联网,可以直接把 MockInterceptor 禁用掉,通过BuildConfig.DEBUG开关控制。

4.2 模拟延迟、错误响应和 Token 校验

Mock 接口做出来后,不能让它一直秒回,否则异常处理代码根本测不出来。需要手动给模拟接口加延迟和错误响应,这样才能暴露问题。加延迟很简单,在intercept方法里插入Thread.sleep(600)即可:

// 模拟 600ms 网络延迟,测试加载动画是否正常 try { Thread.sleep(600); } catch (InterruptedException e) { e.printStackTrace(); }

600 毫秒是一个比较接近真实弱网的数值,太长会浪费时间,太短测不出 loading 效果。除了延迟,还要模拟 401 Token 过期。评分人员如果先登录拿到 Token,再清掉本地数据后重新请求列表,你的 App 应该弹出“登录过期,请重新登录”,而不是崩溃。在MockInterceptor中可以通过检查请求头的方式实现:

if ("/api/news/list".equals(path)) { String token = chain.request().header("Authorization"); if (TextUtils.isEmpty(token)) { return buildJsonResponse(chain, "{\"code\":401,\"message\":\"未登录或登录过期\"}"); } }

这里有一个业务约定:请求列表时必须在 Header 里带上Authorization: token。这个约定在真实接口中也很常见,早期训练就养成这个习惯,后面接真实后端时不用改代码。返回code=401后,前端要判断这个值并跳回登录页,同时清空本地缓存,不能只弹一个 Toast 不处理。错误响应方面,可以再模拟一个code=500的返回,用来测试列表页的加载失败占位图,但要避免所有接口都是 500,否则评分人员点进页面时看不到正常数据。

4.3 联调验收清单:把功能点变成可勾选的表

接口联调不是“能跑就行”,而是要有一个明确的验收过程。我通常会准备一张表格,让队员拿着对照逐项打勾。这张表的核心作用是防止自测时只走正常路径,漏掉异常路径。下面是一个适用于大多数赛题模块的验收清单:

检查项操作步骤预期结果
登录成功输入正确账号密码进入首页,Token写入本地
登录失败输入错误密码提示错误,不跳转
登录保持杀掉App重新打开自动进入首页,不用重新登录
列表加载打开首页显示 Mock 数据,加载框消失
列表断网禁用网络后打开列表显示缓存数据或空状态占位图
详情跳转点击列表项进入详情页,字段完整
收藏功能点击收藏图标图标变为选中态,重启后仍保留

这张表里的每一项,都对应一个可以在评分表上被扣分的点。我在训练时会让队员自己当“评分员”,互相走一遍表,谁漏了一项就给对方报一个真实的 bug。这种练习比多写 20 行代码更能提升赛场稳定性,因为很多学生在赛场上不是不会写,而是只顾着写新功能,忘了回头验证前面已经做完的页面。

5. 备赛避坑指南:赛场上最容易翻车的 5 个细节

5.1 现象:界面写完了,运行却白屏

有学生把登录页写好,布局预览看起来一切正常,但一装到模拟器上就白屏。Logcat 里报的往往是Caused by: java.lang.ClassNotFoundException或者You need to use a Theme.AppCompat theme之类的错误。这个问题最常见的原因是:Activity 继承AppCompatActivity,但工程主题没有继承Theme.AppCompat。在AndroidManifest.xml里给 Activity 指定一个不兼容的主题,或者直接没设置主题,都会导致白屏。

解决方法是修改AndroidManifest.xml中的 application 标签,统一使用带 AppCompat 的主题:android:theme="@style/Theme.AppCompat.Light.NoActionBar"。如果赛题要求无标题栏、全屏展示,可以用NoActionBar变体;如果要求自定义标题,就在布局里自己写。还有一个容易被忽略的点:新建工程时如果选了Empty Activity,系统默认会生成一个theme,不要删掉MainActivity后再手动新建LoginActivity时漏掉主题声明。

5.2 现象:接口请求一直失败,报错里写着 “Cleartext HTTP traffic not permitted”

很多中职学生第一次在真机上调试时都会踩这个坑。赛题给出的后端接口可能是http://开头,而 Android 9 及以上默认禁止明文 HTTP 访问。在真机上测试时,系统会直接抛出Cleartext HTTP traffic not permitted,导致请求全部失败。这不是代码逻辑的问题,而是安全策略限制。

解决方法是在AndroidManifest.xml的 application 标签下加一行android:usesCleartextTraffic="true"。如果评分环境要求必须使用 HTTPS,这一项就不要再保留,否则会留下安全隐患。训练时为了快速联调可以临时打开,提交前要重新确认是否需要关闭。另外,真机请求本机后端时,不能写localhost或127.0.0.1,要写电脑在局域网里的 IP 地址,比如http://192.168.3.88:8080/api/login,否则手机会找不到目标机器,这个也算学生最容易忽略的参数。

5.3 现象:打包后图片和图标全部消失

页面在开发机上显示正常,一打包安装到另一台设备,图片全部变成空白,Logcat 里也没有明显报错。这种问题多半是资源文件放错了位置。赛题素材包里经常会有png、jpg、webp多种格式,如果你把jpg图片放进了res/drawable,布局里引用@drawable/banner本身没问题,但如果文件名中间带横线或大写字母,比如banner-home.png或Tab_Bg.png,编译阶段会直接报资源名不合法。还有一种情况是图片放在assets下,代码里却用R.drawable.xxx去引用,自然找不到资源。

解决方法是:在布局里用@drawable/xxx引用的图片,必须放在res/drawable目录,文件名只能包含小写字母、数字和下划线;在代码里用openFd("xxx.png")读取的图片,必须放在assets目录。提交之前用 Android Studio 的Build > Analyze APK看一眼 APK 里是否包含这些资源,这个步骤一分钟就能排除大半资源问题。

5.4 现象:在评分环境里编译失败,原因却是本机 Gradle 版本不对

不少学生开发机上一切正常,代码提交后,评分环境一打开就报 Gradle 同步失败。这不是赛题代码的问题,而是你在工程里引用了某个只在开发机本地存在的依赖,或者 Gradle 插件版本过高。中职赛项的评分电脑不一定有外网,不能现场下载新版依赖,所以我在训练时一直坚持一个原则:不引入任何不必要的第三方库,优先用原生控件和 AndroidX 自带的组件。比如图片加载用 Glide 没问题,但如果不是必须,也可以先用ImageView.setImageResource顶住。

另一个解决方案是提前把项目完整 Clean 一遍,再到另一个目录重新打开编译一次。这个过程能暴露出“依赖没缓存”“SDK 路径写死”“项目名带中文”等问题。特别注意项目路径不能出现中文和空格,赛题提交时如果压缩包解压路径带中文,Gradle 可能直接找不到ndk或sdk,这属于最冤的翻车情况。

5.5 现象:时间不够,最后草草提交了一个无法编译的工程

每次比赛都有学生因为前面抠界面花太多时间,最后 20 分钟才发现还有两个核心按钮没绑定事件,只能把没有编译通过的工程直接提交。这个坑的根源不是时间不够,而是没有在赛程中做“阶段性可运行”检查。我见过最好的备赛习惯是:每完成一个页面,就编译运行一次;每完成一个功能点,就用真机点一遍。这样即使最后真的做不完,提交出去的也是一个能跑的部分版本,至少能拿到已完成模块的分数。

如果时间真的不够,优先保证登录和首页两个模块能跑通。这两个模块几乎是所有移动应用赛题的共同入口,也是评分人员第一个操作的点,入口打不开,后面再好看的功能都没机会展示。宁可把详情页做得简单一点,也要让首页列表出数据,这个原则一定要提前刻在脑子里。

6. 最后一周的冲刺:把验收清单变成肌肉记忆

最后一周不建议再学新框架或新控件,而是要把已经写过的代码练成“闭眼也能写”的程度。我会让学生在倒计时的每天上午做一次完整模拟赛,从解压赛题包到打包提交,全程计时。下午不做新需求,只做三件事:第一,把前一天模拟赛里暴露的问题修掉;第二,把第 4 章那张验收清单再走两遍;第三,把常用工具类(CacheManager、MockInterceptor、JsonUtil)整理成一个模板工程,熟悉到可以直接默写。

还有一个很实用的习惯:用 Git 做本地版本管理。不需要会复杂分支操作,只要每完成一个阶段就执行一次git add .和git commit,相当于给工程买了一份后悔药。万一改坏了某个页面,还能回退到之前能运行的版本,不会因为一个空指针异常卡半小时。

冲刺阶段要刻意训练的是“快速定位问题”的能力。比如模拟器白屏,先看 Logcat 红色异常;接口报错,先看请求的 URL 和响应状态码;图片不显示,先确认资源路径。这套排查顺序可以提前写在一张纸质表上放在键盘旁边,赛场上紧张到大脑空白时,照着表一步步走,比临时回忆靠谱得多。

带学生备赛这些年,我最大的教训是:赛场上最重要的不是你写了多少行代码,而是你提交前敢不敢打开自己写的 App,把任务书里的每一个按钮都点一遍。很多平时练得不错的学生,最后输在“没时间检查”上。把这句话留给将要上场的你,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询