Kotlin 的统一调度架构

395 阅读2分钟

统一管理:所有任务集中管理,便于维护和扩展
解耦设计:任务调度与具体业务逻辑分离,提高可测试性
灵活配置:支持不同任务类型设置不同轮询间隔
资源优化:自动管理任务生命周期,避免无效轮询
可扩展性:易于添加新功能如优先级管理、网络感知等

调度.drawio.png

核心组件

1. 轮询调度中心 (PollingScheduler)

object PollingScheduler {
    private val taskManager = PollingManager()
    
    // 注册轮询任务
    fun registerTask(taskType: PollingTaskType, fetcher: DataFetcher<out Any>) {
        taskManager.registerTask(taskType, fetcher)
    }
    
    // 启动指定类型的轮询任务
    fun startPolling(taskType: PollingTaskType) {
        taskManager.startPolling(taskType)
    }
    
    // 停止指定类型的轮询任务
    fun stopPolling(taskType: PollingTaskType) {
        taskManager.stopPolling(taskType)
    }
    
    // 清除所有轮询任务
    fun clearAllTasks() {
        taskManager.clearAllTasks()
    }
}

2. 轮询任务管理器 (PollingManager)

class PollingManager private constructor() {
    companion object {
        val instance: PollingManager by lazy(LazyThreadSafetyMode.NONE) {
            PollingManager()
        }
    }

    private val taskGroups = mutableMapOf<PollingTaskType, PollingTaskGroup>()
    
    fun registerTask(taskType: PollingTaskType, fetcher: DataFetcher<out Any>) {
        val group = taskGroups.getOrPut(taskType) { PollingTaskGroup(taskType) }
        group.registerFetcher(fetcher)
    }
    
    fun startPolling(taskType: PollingTaskType) {
        taskGroups[taskType]?.startAll()
    }
    
    fun stopPolling(taskType: PollingTaskType) {
        taskGroups[taskType]?.stopAll()
    }
    
    fun clearAllTasks() {
        taskGroups.values.forEach { it.stopAll() }
        taskGroups.clear()
    }
}

3. 轮询任务组 (PollingTaskGroup)

class PollingTaskGroup(val taskType: PollingTaskType) {
    private val fetchers = mutableListOf<DataFetcher<out Any>>()
    private var isRunning = false
    
    fun registerFetcher(fetcher: DataFetcher<out Any>) {
        if (!fetchers.contains(fetcher)) {
            fetchers.add(fetcher)
        }
    }
    
    fun startAll() {
        if (!isRunning && fetchers.isNotEmpty()) {
            fetchers.forEach { it.start() }
            isRunning = true
        }
    }
    
    fun stopAll() {
        if (isRunning) {
            fetchers.forEach { it.stop() }
            isRunning = false
        }
    }
}

4. 轮询任务接口 (PollingTask)

interface PollingTask {
    fun start()
    fun stop()
    fun isRunning(): Boolean
    fun getInterval(): Long
}

5. 数据抓取器 (DataFetcher)

interface DataFetcher<T> {
    val key: String
    val interval: Long
    
    fun start()
    fun stop()
    fun fetchData(): T
    fun onResult(result: T)
    fun onError(error: Exception)
}

三、实现示例

1. 轮询任务类型枚举

enum class PollingTaskType(val interval: Long) {
    SCORE(5000),
    TECH_STATISTIC(10000),
    MATCH_EVENT(3000),
    ONLINE_USERS(15000)
}

2. 分数数据抓取器

class ScoreFetcher(private val matchId: String) : DataFetcher<ScoreData> {
    override val key: String = "score_$matchId"
    override val interval: Long = PollingTaskType.SCORE.interval
    
    override fun start() {
        // 实现启动逻辑
    }
    
    override fun stop() {
        // 实现停止逻辑
    }
    
    override fun fetchData(): ScoreData {
        // 实现数据获取逻辑
        return ScoreData()
    }
    
    override fun onResult(result: ScoreData) {
        // 处理结果
    }
    
    override fun onError(error: Exception) {
        // 处理错误
    }
}

3. 在Activity中使用

class DetailActivity : AppCompatActivity() {
    private lateinit var scoreFetcher: ScoreFetcher
    private lateinit var techStatFetcher: TechStatisticFetcher
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val matchId = intent.getStringExtra("MATCH_ID") ?: ""
        
        scoreFetcher = ScoreFetcher(matchId)
        techStatFetcher = TechStatisticFetcher(matchId)
        
        PollingScheduler.registerTask(PollingTaskType.SCORE, scoreFetcher)
        PollingScheduler.registerTask(PollingTaskType.TECH_STATISTIC, techStatFetcher)
        
        PollingScheduler.startPolling(PollingTaskType.SCORE)
        PollingScheduler.startPolling(PollingTaskType.TECH_STATISTIC)
    }
    
    override fun onDestroy() {
        super.onDestroy()
        PollingScheduler.stopPolling(PollingTaskType.SCORE)
        PollingScheduler.stopPolling(PollingTaskType.TECH_STATISTIC)
    }
}

四、功能扩展

1. 增加优先级管理

enum class PollingTaskPriority(val level: Int) {
    HIGH(3),
    MEDIUM(2),
    LOW(1)
}

class PollingTaskGroup(
    val taskType: PollingTaskType,
    val priority: PollingTaskPriority = PollingTaskPriority.MEDIUM
) {
    // ...其他代码
}

2. 添加生命周期感知

class LifecycleAwareFetcher<T>(
    private val fetcher: DataFetcher<T>,
    private val lifecycleScope: LifecycleCoroutineScope
) : DataFetcher<T> by fetcher {
    
    override fun start() {
        lifecycleScope.launch {
            fetcher.start()
        }
    }
    
    override fun stop() {
        lifecycleScope.launch {
            fetcher.stop()
        }
    }
}

3. 添加网络状态监听

object NetworkAwarePollingManager {
    private val connectivityManager = // 获取ConnectivityManager
    
    fun init(context: Context) {
        // 注册网络状态监听
    }
    
    fun onNetworkStateChanged(isConnected: Boolean) {
        if (isConnected) {
            PollingScheduler.startAllTasks()
        } else {
            PollingScheduler.stopAllTasks()
        }
    }
}

该架构设计遵循了单一职责原则和开闭原则,通过接口抽象实现了良好的可扩展性,同时利用单例模式确保了全局轮询任务的一致性管理。