Android应用点击按钮5次后无响应或闪退问题求助
问题描述
开发Android应用时遇到以下问题:
- 需求:点击按钮5次后进入对应环节;若10分钟内未点击指定TextView,则返回初始按钮点击页面。
- 异常:运行到该环节时应用无响应或闪退。
- 使用组件:ImageView、Button、TextView
- 相关代码:
public void PreparingActivity() { Button Hbutton1 = findViewById(R.id.HiddenButton1); TextView start = findViewById(R.id.START); ImageView logo = findViewById(R.id.Logo); if (5 == acceptance) { Hbutton1.setVisibility(View.INVISIBLE); start.setVisibility(View.VISIBLE); logo.setVisibility(View.INVISIBLE); for (int i = 0; i < 10; i++) { for (int j = 0; j < 60; j++) { start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { countison = true; } }); if (countison) { break; } SystemClock.sleep(1000); } if (countison) { break; } } if (!countison) { start.setVisibility(View.INVISIBLE); logo.setVisibility(View.VISIBLE); } else { acceptance = 0; TimerStarts(); } } }
- CPU占用相关日志(部分):
CPU usage from 154450ms to 0ms ago (2023-02-12 10:35:30.281 to 2023-02-12 10:38:04.730):
1.8% 293/android.hardware.bluetooth@1.1-service.sim: 0% user + 1.8% kernel
0.9% 3817/com.example.szamlalo: 0% user + 0.8% kernel / faults: 1755 minor
0.7% 303/android.hardware.graphics.composer@2.3-service: 0% user + 0.7% kernel
0.6% 537/system_server: 0% user + 0.5% kernel / faults: 2140 minor
0.5% 362/surfaceflinger: 0% user + 0.5% kernel / faults: 5 minor
...
问题原因分析
- 主线程阻塞:代码中用
SystemClock.sleep(1000)在主线程循环休眠,Android主线程负责UI渲染和用户交互,长时间阻塞会触发ANR(应用无响应)甚至闪退。 - 重复设置点击监听:循环中每次给
startTextView设置新的OnClickListener,属于冗余操作,还可能引发内存泄漏。 - 交互逻辑失效:主线程休眠期间,用户点击事件无法被处理,
onClick回调根本不会执行,导致countison变量永远不会被置为true,逻辑完全失效。
修复方案
使用Android官方提供的CountDownTimer实现异步倒计时,避免阻塞主线程,同时优化点击事件处理:
private CountDownTimer countDownTimer; public void PreparingActivity() { Button Hbutton1 = findViewById(R.id.HiddenButton1); TextView start = findViewById(R.id.START); ImageView logo = findViewById(R.id.Logo); if (5 == acceptance) { Hbutton1.setVisibility(View.INVISIBLE); start.setVisibility(View.VISIBLE); logo.setVisibility(View.INVISIBLE); // 仅设置一次点击监听 start.setOnClickListener(view -> { if (countDownTimer != null) { countDownTimer.cancel(); } acceptance = 0; TimerStarts(); start.setVisibility(View.INVISIBLE); logo.setVisibility(View.VISIBLE); }); // 初始化10分钟倒计时(总时长10*60*1000毫秒,每秒回调一次) countDownTimer = new CountDownTimer(10 * 60 * 1000, 1000) { @Override public void onTick(long millisUntilFinished) { // 可选:在这里更新倒计时显示,比如start.setText("剩余 " + millisUntilFinished / 1000 + " 秒"); } @Override public void onFinish() { // 倒计时结束,恢复初始页面状态 start.setVisibility(View.INVISIBLE); logo.setVisibility(View.VISIBLE); Hbutton1.setVisibility(View.VISIBLE); } }; countDownTimer.start(); } } // 在Activity销毁时取消倒计时,防止内存泄漏 @Override protected void onDestroy() { super.onDestroy(); if (countDownTimer != null) { countDownTimer.cancel(); } }
关键优化点
- 用
CountDownTimer替代主线程循环休眠,异步执行倒计时,不阻塞UI交互。 - 点击监听仅设置一次,避免冗余操作和潜在内存泄漏。
- 在
onDestroy中取消倒计时,确保Activity销毁后定时器不会继续运行。
内容的提问来源于stack exchange,提问作者szabeeee
相关产品推荐
相关产品推荐

