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

如何在Android中结合WorkManager实现异步DNS解析?

适配WorkManager的异步DNS解析方案

你不需要寻找专门的替代API,直接将DnsResolver与WorkManager结合即可,下面是几种简便的实现方式:

方案一:在Worker中用CountDownLatch同步化异步调用(Java/Kotlin通用)

WorkManager的Worker.doWork()方法本身运行在后台线程,因此可以用CountDownLatch将DnsResolver的异步回调转为同步执行,避免主线程阻塞:

class DnsWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        val domain = inputData.getString("DOMAIN") ?: return Result.failure()
        val latch = CountDownLatch(1)
        var dnsResult: List<DnsRecord>? = null
        var error: Exception? = null

        DnsResolver.query(
            DnsResolver.getDefault(),
            domain,
            DnsRecord.TYPE_A,
            Executors.newSingleThreadExecutor(),
            object : DnsResolver.Callback<List<DnsRecord>> {
                override fun onSuccess(result: List<DnsRecord>) {
                    dnsResult = result
                    latch.countDown()
                }

                override fun onFailure(e: Exception) {
                    error = e
                    latch.countDown()
                }
            }
        )

        try {
            latch.await() // 等待异步解析完成
        } catch (e: InterruptedException) {
            return Result.failure()
        }

        return if (error != null) {
            Result.failure()
        } else {
            val ips = dnsResult?.map { it.address.hostAddress } ?: emptyList()
            val outputData = Data.Builder()
                .putStringArrayList("IPS", ArrayList(ips))
                .build()
            Result.success(outputData)
        }
    }
}

方案二:用协程包装DnsResolver(Kotlin推荐)

如果你的项目使用Kotlin协程,借助CoroutineWorker和挂起函数,可以更优雅地封装异步DNS调用,避免回调样板代码:

第一步:封装挂起函数扩展

suspend fun DnsResolver.querySuspend(
    domain: String,
    recordType: Int = DnsRecord.TYPE_A
): List<DnsRecord> = suspendCancellableCoroutine { continuation ->
    query(
        this,
        domain,
        recordType,
        Executors.newSingleThreadExecutor(),
        object : DnsResolver.Callback<List<DnsRecord>> {
            override fun onSuccess(result: List<DnsRecord>) {
                continuation.resume(result)
            }

            override fun onFailure(e: Exception) {
                continuation.resumeWithException(e)
            }
        }
    )

    // 当Worker被取消时,同步取消DNS查询
    continuation.invokeOnCancellation {
        cancel()
    }
}

第二步:实现CoroutineWorker

class CoroutineDnsWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        val domain = inputData.getString("DOMAIN") ?: return Result.failure()
        return try {
            val dnsRecords = DnsResolver.getDefault().querySuspend(domain)
            val ips = dnsRecords.map { it.address.hostAddress }
            val outputData = Data.Builder()
                .putStringArrayList("IPS", ArrayList(ips))
                .build()
            Result.success(outputData)
        } catch (e: Exception) {
            // 处理解析失败逻辑
            Result.failure()
        }
    }
}

方案三:使用第三方DNS库(如OkHttp)

如果觉得系统DnsResolver的回调机制繁琐,可以直接使用OkHttp的Dns接口,它默认是同步实现,可直接在Worker中调用:

class OkHttpDnsWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    private val systemDns = Dns.SYSTEM

    override suspend fun doWork(): Result {
        val domain = inputData.getString("DOMAIN") ?: return Result.failure()
        return try {
            val inetAddresses = systemDns.lookup(domain)
            val ips = inetAddresses.map { it.hostAddress }
            val outputData = Data.Builder()
                .putStringArrayList("IPS", ArrayList(ips))
                .build()
            Result.success(outputData)
        } catch (e: Exception) {
            Result.failure()
        }
    }
}

关键说明

  • WorkManager的Worker线程本身就是后台线程,因此无论采用同步还是异步适配方式,都不会阻塞主线程。
  • 如果你需要自定义DNS服务器,OkHttp的Dns接口支持自定义实现,灵活性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:55:55