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

Android 12 AppSearch开发中Futures引用缺失问题及依赖导入、Kotlin协程替代方案咨询

解决AppSearch中Futures引用问题与协程替代方案

一、修复Futures和FutureCallback的依赖问题

你遇到的Futures和FutureCallback引用未知的问题,核心是缺少对应的基础依赖包。在现有依赖配置中添加以下内容即可解决:

implementation "androidx.concurrent:concurrent-futures:1.1.0"

同时要确保代码中导入正确的类:

import androidx.concurrent.futures.Futures
import androidx.concurrent.futures.FutureCallback

另外建议把concurrent-futures-ktx的版本和上面的concurrent-futures统一为1.1.0,避免版本冲突。

二、配置mExecutor

mExecutor是用来执行后台耗时任务的线程池,AppSearch的创建会话、设置Schema、写入文档等操作都不能在主线程执行,所以需要配置一个后台线程池:

方式1:创建单线程线程池

这是最简单的后台线程配置,适合轻量的AppSearch操作:

import java.util.concurrent.Executors

private val mExecutor = Executors.newSingleThreadExecutor()

方式2:使用固定大小线程池

如果有多个并发的AppSearch操作,可以用固定线程数的线程池:

import java.util.concurrent.Executors

private val mExecutor = Executors.newFixedThreadPool(2)

注意:绝对不要用主线程作为mExecutor,否则会触发ANR(应用无响应)。

三、使用Kotlin协程替代Futures(更优雅的方案)

既然你用的是Kotlin,协程是比Futures更简洁的异步处理方式,完全可以替代原有的回调式代码,步骤如下:

1. 添加协程依赖

确保项目中已添加这些依赖:

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2" // 用于lifecycleScope
implementation "androidx.concurrent:concurrent-futures-ktx:1.1.0"

2. 协程版本的代码实现

利用asDeferred()扩展函数将ListenableFuture转换为协程的Deferred,再用await()等待结果,代码逻辑更线性:

import android.util.Log
import androidx.appsearch.app.PutDocumentsRequest
import androidx.appsearch.app.SetSchemaRequest
import androidx.appsearch.localstorage.LocalStorage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

// 在Activity/Fragment中使用lifecycleScope自动绑定生命周期,避免内存泄漏
lifecycleScope.launch {
    try {
        // 创建搜索会话(切换到IO线程执行耗时操作)
        val session = withContext(Dispatchers.IO) {
            LocalStorage.createSearchSession(
                LocalStorage.SearchContext.Builder(this@YourActivity, "notes_app")
                    .build()
            ).await()
        }

        // 设置Schema
        withContext(Dispatchers.IO) {
            session.setSchema(
                SetSchemaRequest.Builder().addDocumentClasses(Note::class.java)
                    .build()
            ).await()
        }

        // 写入文档并处理结果
        val putResult = withContext(Dispatchers.IO) {
            session.put(
                PutDocumentsRequest.Builder().addDocuments(note).build()
            ).await()
        }

        // 处理成功/失败结果,这里在主线程可以直接更新UI
        val successfulResults = putResult.successes
        val failedResults = putResult.failures
    } catch (t: Throwable) {
        Log.e(TAG, "AppSearch操作失败", t)
    }
}

说明:

  • lifecycleScope会自动跟随Activity/Fragment的生命周期销毁,避免内存泄漏;
  • withContext(Dispatchers.IO)将耗时操作切换到后台线程,不阻塞主线程;
  • 统一的try-catch可以处理所有异常,比回调式的FutureCallback更易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 16:12:44