Android Studio中如何实现每秒运行的Java方法以检测ToggleButton状态?
递归调用导致崩溃的核心原因是:每次递归都会在调用栈中新增方法帧,持续运行后会耗尽栈内存,抛出StackOverflowError。以下是两种安全可靠的实现方式:
方案一:使用Handler实现主线程定时任务
Handler是Android中处理主线程定时任务的常用方式,不会产生栈溢出问题,且天然支持UI操作:
private Handler mCheckHandler = new Handler(Looper.getMainLooper()); private Runnable mCheckTask = new Runnable() { @Override public void run() { checkToggleStateAndVibrate(); // 1秒后再次执行任务 mCheckHandler.postDelayed(this, 1000); } }; // 核心检测与震动逻辑 private void checkToggleStateAndVibrate() { // 仅当ToggleButton处于选中状态时继续判断 if (!tb.isChecked()) return; // 获取当前小时与分钟 Calendar now = Calendar.getInstance(); int curHour = now.get(Calendar.HOUR_OF_DAY); int curMin = now.get(Calendar.MINUTE); // 匹配设定时间时触发震动 if (curHour == hour && curMin == minutes) { // 检查震动权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.VIBRATE) == PackageManager.PERMISSION_GRANTED) { Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android 8.0及以上使用VibrationEffect vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE)); } else { // 低版本直接调用vibrate方法 vibrator.vibrate(500); } } } } } // 在Activity生命周期中启动/停止任务,避免内存泄漏 @Override protected void onResume() { super.onResume(); mCheckHandler.post(mCheckTask); } @Override protected void onPause() { super.onPause(); mCheckHandler.removeCallbacks(mCheckTask); }
方案二:使用ScheduledExecutorService实现后台定时任务
适合需要在后台执行检测逻辑的场景,若需访问UI组件需切换到主线程:
private ScheduledExecutorService mScheduler = Executors.newSingleThreadScheduledExecutor(); private ScheduledFuture<?> mCheckFuture; // 启动定时任务 private void startScheduledCheck() { mCheckFuture = mScheduler.scheduleAtFixedRate(() -> { // 切换到主线程操作UI组件 runOnUiThread(this::checkToggleStateAndVibrate); }, 0, 1, TimeUnit.SECONDS); } // 停止定时任务 private void stopScheduledCheck() { if (mCheckFuture != null && !mCheckFuture.isCancelled()) { mCheckFuture.cancel(true); } } // 同样在生命周期中管理任务 @Override protected void onResume() { super.onResume(); startScheduledCheck(); } @Override protected void onPause() { super.onPause(); stopScheduledCheck(); } // 复用方案一中的checkToggleStateAndVibrate方法
必要配置
在AndroidManifest.xml中声明震动权限:
<uses-permission android:name="android.permission.VIBRATE" />
注意:VIBRATE权限属于Android正常权限,无需动态申请,但仍建议通过
checkSelfPermission做兼容性检查,避免特殊场景下的权限问题。
内容的提问来源于stack exchange,提问作者SKYWALKER
相关产品推荐
相关产品推荐

