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

如何在Executor/FutureTask流程中用Lambda实现Android异步任务回调?

问题描述

现有如下异步任务相关代码:

public interface TaskCallback {
    void onTaskCompleted(Boolean result);
    void onTaskFailed(Exception e);
}

public class AsyncTaskExample {
    private final Executor executor = Executors.newSingleThreadExecutor();

    public void executeAsyncTask(TaskCallback callback) {
        FutureTask<Boolean> taskSyncFiles = new FutureTask<>(() -> {
            // 具体任务逻辑
            return true;
        });

        executor.execute(taskSyncFiles);
        executor.execute(() -> {
            try {
                Boolean result = taskSyncFiles.get();
                callback.onTaskCompleted(result);
            } catch (InterruptedException | ExecutionException e) {
                callback.onTaskFailed(e);
            }
        });
    }
}

希望在Android Activity中通过Lambda表达式分别传入完成和失败回调,调用方式如下,但无法正常运行:

myTask.executeAsyncTask(result -> {
    System.out.println("Task completed with result: " + result);
}, e -> {
    e.printStackTrace();
});

请问该如何正确实现?

解决方案

问题核心是你定义的executeAsyncTask方法仅接收一个TaskCallback接口参数,但调用时传入了两个Lambda表达式。以下是两种可行的实现方案:

方案一:新增重载方法,拆分回调参数

  1. 先定义两个独立的函数式接口,分别对应成功和失败回调:
@FunctionalInterface
public interface OnSuccessCallback {
    void onSuccess(Boolean result);
}

@FunctionalInterface
public interface OnFailureCallback {
    void onFailure(Exception e);
}
  1. 在AsyncTaskExample中新增重载的executeAsyncTask方法,接收上述两个回调参数:
public class AsyncTaskExample {
    private final Executor executor = Executors.newSingleThreadExecutor();

    // 保留原有方法,兼容旧调用逻辑
    public void executeAsyncTask(TaskCallback callback) {
        FutureTask<Boolean> taskSyncFiles = new FutureTask<>(() -> {
            // 具体任务逻辑
            return true;
        });

        executor.execute(taskSyncFiles);
        executor.execute(() -> {
            try {
                Boolean result = taskSyncFiles.get();
                callback.onTaskCompleted(result);
            } catch (InterruptedException | ExecutionException e) {
                callback.onTaskFailed(e);
            }
        });
    }

    // 新增重载方法,支持拆分回调传入
    public void executeAsyncTask(OnSuccessCallback successCallback, OnFailureCallback failureCallback) {
        FutureTask<Boolean> taskSyncFiles = new FutureTask<>(() -> {
            // 具体任务逻辑
            return true;
        });

        executor.execute(taskSyncFiles);
        executor.execute(() -> {
            try {
                Boolean result = taskSyncFiles.get();
                successCallback.onSuccess(result);
            } catch (InterruptedException | ExecutionException e) {
                failureCallback.onFailure(e);
            }
        });
    }
}
  1. 现在即可在Activity中按预期方式调用:
AsyncTaskExample myTask = new AsyncTaskExample();
myTask.executeAsyncTask(result -> {
    // Android中子线程不能更新UI,需切换到主线程操作
    runOnUiThread(() -> {
        Log.d("TaskLog", "Task completed with result: " + result);
    });
}, e -> {
    e.printStackTrace();
});

方案二:给TaskCallback添加静态构造方法

如果不想新增接口,可以通过给TaskCallback添加静态方法,快速构建实例,适配Lambda写法:

public interface TaskCallback {
    void onTaskCompleted(Boolean result);
    void onTaskFailed(Exception e);

    // 静态方法:快速创建包含双回调的实例
    static TaskCallback of(OnSuccessCallback success, OnFailureCallback failure) {
        return new TaskCallback() {
            @Override
            public void onTaskCompleted(Boolean result) {
                success.onSuccess(result);
            }

            @Override
            public void onTaskFailed(Exception e) {
                failure.onFailure(e);
            }
        };
    }
}

// 仍需定义两个基础函数式接口
@FunctionalInterface
public interface OnSuccessCallback {
    void onSuccess(Boolean result);
}

@FunctionalInterface
public interface OnFailureCallback {
    void onFailure(Exception e);
}

调用方式如下:

myTask.executeAsyncTask(TaskCallback.of(
    result -> {
        runOnUiThread(() -> {
            Log.d("TaskLog", "Task completed: " + result);
        });
    },
    e -> {
        e.printStackTrace();
    }
));

关键注意事项

  • UI线程切换:Android中子线程无法更新UI,回调内如果需要操作UI,必须通过runOnUiThread、Handler或LiveData切换到主线程。
  • 资源释放:使用Executors.newSingleThreadExecutor()创建的线程池,需在Activity销毁时关闭,避免内存泄漏:
@Override
protected void onDestroy() {
    super.onDestroy();
    // 需将executor改为可访问,比如设为public或提供shutdown方法
    myTask.executor.shutdown();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:14:56