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

在ROOM中复用Callable代码:MVVM架构TODO应用代码优化问询

优化方案

1. 核心复用:提取通用数据库执行方法

你的代码重复了线程池创建、Callable封装、异常处理逻辑,首先抽取出通用方法,将具体的DAO操作作为参数传入:

首先在你的Repository类中定义全局复用的线程池(避免每次创建新线程池带来的开销):

private final ExecutorService dbExecutor = Executors.newSingleThreadExecutor();

然后编写通用执行方法,统一处理线程提交、异常捕获:

/**
 * 通用数据库操作执行方法
 * @param operation 具体的DAO操作逻辑
 * @return 操作结果,异常时返回空集合(针对列表类型)或null
 */
private <T> T executeDbOperation(Callable<T> operation) {
    try {
        return dbExecutor.submit(operation).get();
    } catch (ExecutionException e) {
        // 可根据需求添加自定义异常处理,比如日志上报
        Throwable rootCause = e.getCause();
        Log.e("DB_OP", "数据库操作失败", rootCause);
    } catch (InterruptedException e) {
        e.printStackTrace();
        // 恢复线程中断状态,避免影响后续逻辑
        Thread.currentThread().interrupt();
    }
    // 针对集合类型返回空集合,避免上层空指针
    if (operation instanceof Callable<? extends Collection>) {
        return (T) Collections.emptyList();
    }
    return null;
}

2. 简化原有业务方法

利用Java 8+的Lambda表达式替代匿名Callable,原有方法可以简化为一行代码:

public List<Task> getAllUnCompletedTasksAsList() {
    return executeDbOperation(() -> appDataBase.taskDao().getAllUnCompletedTasksAsList());
}

public List<Task> getCompletedTasksAsList() {
    return executeDbOperation(() -> appDataBase.taskDao().getCompletedTasksAsList());
}

public List<Task> getWeeklyTasksAsList() {
    return executeDbOperation(() -> appDataBase.taskDao().getWeeklyTasksAsList());
}

3. 线程池生命周期管理

为避免内存泄漏,在Repository销毁时关闭线程池(比如在ViewModel的onCleared()方法中调用):

public void cleanup() {
    dbExecutor.shutdown();
}

4. 更贴合MVVM的进阶优化

当前使用future.get()是阻塞式调用,如果在主线程调用会导致UI卡顿。ROOM本身支持LiveData自动处理线程切换,更符合MVVM的响应式设计:

用LiveData实现异步非阻塞

  1. 在DAO层定义返回LiveData的方法:
@Query("SELECT * FROM tasks WHERE completed = 0")
LiveData<List<Task>> getAllUnCompletedTasks();

@Query("SELECT * FROM tasks WHERE completed = 1")
LiveData<List<Task>> getCompletedTasks();

@Query("SELECT * FROM tasks WHERE due_date >= :startOfWeek AND due_date <= :endOfWeek")
LiveData<List<Task>> getWeeklyTasks(long startOfWeek, long endOfWeek);
  1. 在Repository直接返回LiveData,ROOM会自动在后台线程执行查询,主线程观察:
public LiveData<List<Task>> getAllUnCompletedTasks() {
    return appDataBase.taskDao().getAllUnCompletedTasks();
}

public LiveData<List<Task>> getCompletedTasks() {
    return appDataBase.taskDao().getCompletedTasks();
}

public LiveData<List<Task>> getWeeklyTasks(long startOfWeek, long endOfWeek) {
    return appDataBase.taskDao().getWeeklyTasks(startOfWeek, endOfWeek);
}
  1. 在ViewModel中观察LiveData,自动更新UI:
public class TaskViewModel extends ViewModel {
    private final TaskRepository repository;
    public final LiveData<List<Task>> unCompletedTasks;

    public TaskViewModel(TaskRepository repository) {
        this.repository = repository;
        unCompletedTasks = repository.getAllUnCompletedTasks();
    }
}

这种方式完全不需要手动处理线程,代码更简洁且符合MVVM架构的响应式理念。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:30:56