You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中Java代码try-catch出现无限循环问题求助

解决Android Room数据库操作导致的无限循环问题

问题根源

你的代码存在典型的LiveData触发循环:点击按钮后通过userViewModel.getId().observe监听用户数据,执行update操作修改数据库后,Room会通知getId返回的LiveData数据更新,观察者回调会再次被触发,进而再次执行update,形成无限循环。而你用的isUpdating标志只能控制按钮点击触发,无法阻止LiveData数据更新带来的重复回调。

解决方案一:使用一次性观察者

给ViewModel添加只监听一次数据变化的方法,避免数据更新时重复触发回调:

修改ViewModel类

// 添加一次性观察方法
public void observeOnceById(int userId, Observer<List<Users>> observer) {
    LiveData<List<Users>> userLiveData = getId(userId);
    userLiveData.observeForever(new Observer<List<Users>>() {
        @Override
        public void onChanged(List<Users> users) {
            observer.onChanged(users);
            // 数据回调后立即移除观察者,避免后续更新触发
            userLiveData.removeObserver(this);
        }
    });
}

修改MainActivity的点击事件

final boolean[] isUpdating = {false};
UserViewModel userViewModel = new ViewModelProvider(this).get(UserViewModel.class);
btnUpdate.setOnClickListener(view -> {
    if (!isUpdating[0]) {
        isUpdating[0] = true;

        Users user = new Users(5, "kylo", "14", "14");
        // 使用一次性观察者替代原observe方法
        userViewModel.observeOnceById(user.getId(), users -> {
            if (users.size() == 1) {
                logger.LogError(tag, "Checked if exist", "true");
                try {
                    int result = userViewModel.update(user);
                    if (result > 0) {
                        logger.LogError(tag, "Update", "success");
                    } else {
                        logger.LogError(tag, "Update", "failed");
                    }
                } catch (ExecutionException | InterruptedException | TimeoutException e) {
                    e.printStackTrace();
                } finally {
                    isUpdating[0] = false;
                }
            } else {
                logger.LogError(tag, "Checked if exist", "false");
                isUpdating[0] = false;
            }
        });
    }
});

解决方案二:同步查询用户是否存在

如果不需要监听数据变化,只是执行"检查存在→更新"的逻辑,可以改用同步查询,完全避免LiveData的自动回调:

修改ViewModel类

// 添加同步查询方法
public List<Users> getByIdSync(int userId) throws ExecutionException, InterruptedException {
    Callable<List<Users>> queryCallable = () -> sqlite_room_dao.getById(userId);
    Future<List<Users>> future = Executors.newSingleThreadExecutor().submit(queryCallable);
    return future.get();
}

修改MainActivity的点击事件

final boolean[] isUpdating = {false};
UserViewModel userViewModel = new ViewModelProvider(this).get(UserViewModel.class);
btnUpdate.setOnClickListener(view -> {
    if (!isUpdating[0]) {
        isUpdating[0] = true;
        
        new Thread(() -> {
            Users user = new Users(5, "kylo", "14", "14");
            try {
                List<Users> users = userViewModel.getByIdSync(user.getId());
                if (users.size() == 1) {
                    logger.LogError(tag, "Checked if exist", "true");
                    int result = userViewModel.update(user);
                    runOnUiThread(() -> {
                        if (result > 0) {
                            logger.LogError(tag, "Update", "success");
                        } else {
                            logger.LogError(tag, "Update", "failed");
                        }
                    });
                } else {
                    logger.LogError(tag, "Checked if exist", "false");
                }
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            } finally {
                runOnUiThread(() -> isUpdating[0] = false);
            }
        }).start();
    }
});

额外优化点

  • 避免每次创建新的Executors.newSingleThreadExecutor(),可以在ViewModel中初始化固定线程池,减少资源消耗。
  • Room的@Update注解可直接接收实体类对象,无需手动传递字段参数,简化sqlite_room_dao.update的实现。

内容的提问来源于stack exchange,提问作者RFlores

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 09:13:19