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

如何使用WorkManager创建通用NetworkRequestWorker?

复用CoroutineWorker处理网络请求的最佳实践

先澄清NowInAndroid的Repository传递问题

你看到的NowInAndroid示例中,Worker并非通过WorkRequest的Data传递Repository,而是通过**依赖注入(如Hilt)**注入到Worker构造函数中的。WorkManager允许通过自定义WorkerFactory创建Worker实例,DI框架会负责注入Repository这类依赖,不需要将其序列化传入Data。


核心抽象方案:泛型Worker + 请求处理器策略

要复用Worker处理不同网络请求,同时避免重复代码,推荐用泛型CoroutineWorker配合请求处理器接口的模式,既统一网络请求的核心逻辑,又能灵活扩展不同请求的业务操作。

1. 定义请求处理器接口

封装每个请求的核心逻辑:执行请求、成功回调、失败回调

interface NetworkRequestHandler<Request, Response> {
    // 执行具体网络请求
    suspend fun executeRequest(request: Request): Result<Response>
    // 请求成功后的业务操作
    suspend fun onSuccess(response: Response)
    // 请求失败后的处理逻辑
    suspend fun onFailure(throwable: Throwable)
}

2. 实现泛型基础Worker

统一处理参数解析、异常捕获、流程调度,避免重复编写Worker模板代码

class GenericNetworkWorker<Request, Response>(
    context: Context,
    params: WorkerParameters,
    private val handler: NetworkRequestHandler<Request, Response>,
    private val jsonConverter: JsonConverter // 封装Gson/Moshi等序列化工具
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            // 从WorkData中读取序列化后的请求参数
            val requestJson = inputData.getString(KEY_REQUEST_PARAMS) 
                ?: return Result.failure(workDataOf(KEY_ERROR to "缺少请求参数"))
            
            // 反序列化为请求实体类
            val request = jsonConverter.fromJson(requestJson, Request::class.java)

            // 执行请求并处理结果
            when (val responseResult = handler.executeRequest(request)) {
                is Result.Success -> {
                    handler.onSuccess(responseResult.data)
                    Result.success()
                }
                is Result.Failure -> {
                    handler.onFailure(responseResult.exception)
                    Result.failure(workDataOf(KEY_ERROR to responseResult.exception.message))
                }
            }
        } catch (e: Exception) {
            handler.onFailure(e)
            Result.failure(workDataOf(KEY_ERROR to e.message))
        }
    }

    companion object {
        const val KEY_REQUEST_PARAMS = "request_params"
        const val KEY_ERROR = "error_message"
    }
}

3. 实现具体请求的处理器

比如登录请求的处理器,专注于该请求的业务逻辑

class LoginRequestHandler(
    private val authRepository: AuthRepository,
    private val userDataStore: UserDataStore
) : NetworkRequestHandler<LoginRequest, LoginResponse> {

    override suspend fun executeRequest(request: LoginRequest): Result<LoginResponse> {
        return authRepository.login(request) // 调用Repository的网络请求方法
    }

    override suspend fun onSuccess(response: LoginResponse) {
        userDataStore.saveAuthToken(response.token) // 成功后保存Token
    }

    override suspend fun onFailure(throwable: Throwable) {
        Log.e("LoginWorker", "登录请求失败", throwable) // 失败后记录日志
    }
}

4. 用依赖注入绑定Worker

以Hilt为例,通过@HiltWorker注解让DI框架管理Worker实例,注入所需的处理器和序列化工具

@HiltWorker
class LoginWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted params: WorkerParameters,
    private val loginHandler: LoginRequestHandler,
    private val jsonConverter: JsonConverter
) : GenericNetworkWorker<LoginRequest, LoginResponse>(context, params, loginHandler, jsonConverter)

5. 创建并执行WorkRequest

将请求参数序列化后传入WorkData,再构建WorkRequest

// 构造请求参数
val loginRequest = LoginRequest(username = "test_user", password = "123456")
// 序列化请求参数
val requestJson = jsonConverter.toJson(loginRequest)
// 组装WorkData
val workData = workDataOf(GenericNetworkWorker.KEY_REQUEST_PARAMS to requestJson)

// 创建WorkRequest并加入队列
val loginWorkRequest = OneTimeWorkRequestBuilder<LoginWorker>()
    .setInputData(workData)
    .build()

WorkManager.getInstance(context).enqueue(loginWorkRequest)

替代方案:请求标识 + Repository驱动

如果请求参数可以通过Repository/本地数据源获取,也可以只传递请求标识(如REQUEST_TYPE字符串),Worker根据标识调用Repository对应方法:

class IdentifiedNetworkWorker(
    context: Context,
    params: WorkerParameters,
    private val authRepository: AuthRepository,
    private val userDataStore: UserDataStore
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        val requestType = inputData.getString(KEY_REQUEST_TYPE) ?: return Result.failure()
        return when (requestType) {
            "LOGIN" -> handleLoginRequest()
            "REFRESH_TOKEN" -> handleRefreshToken()
            else -> Result.failure()
        }
    }

    private suspend fun handleLoginRequest(): Result {
        // 从本地获取登录参数(比如DataStore)
        val loginParams = userDataStore.getPendingLoginParams()
        return try {
            val response = authRepository.login(loginParams)
            userDataStore.saveAuthToken(response.token)
            Result.success()
        } catch (e: Exception) {
            Log.e("LoginWorker", "登录失败", e)
            Result.failure()
        }
    }

    companion object {
        const val KEY_REQUEST_TYPE = "request_type"
    }
}

方案对比

方案优点缺点适用场景
泛型Worker+处理器代码复用率高,逻辑解耦需要依赖DI框架,稍显复杂多类型网络请求场景
单独Worker类逻辑直观,无需额外封装代码重复度高少量简单网络请求场景
请求标识+Repository无需传递复杂参数依赖本地数据源存储参数参数可本地获取的请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:57:11