如何通过Hilt提供带动态query参数的ExamplePagingSource依赖?
核心问题在于Pager要求每次调用pagingSourceFactory时必须返回全新的PagingSource实例,你之前复用实例修改query的方式直接违反了这个规则,因此抛出异常。下面是两种符合Hilt规范的解决方案:
方案一:使用@AssistedInject(推荐,Hilt官方动态参数注入方案)
1. 改造ExamplePagingSource的构造器
用@AssistedInject标记构造方法,固定依赖ExampleBackendService使用普通@Inject注入,动态变化的query用@Assisted标记:
class ExamplePagingSource @AssistedInject constructor( private val backend: ExampleBackendService, @Assisted private val query: String ) : PagingSource<Int, DataItem>() { // ... 你的PagingSource业务实现逻辑 }
2. 创建AssistedFactory接口
定义一个工厂接口并标记@AssistedFactory,用于动态生成带query参数的PagingSource实例:
@AssistedFactory interface ExamplePagingSourceFactory { fun create(query: String): ExamplePagingSource }
3. 在ViewModel中注入工厂并配置Pager
在ViewModel里注入ExamplePagingSourceFactory,然后在Pager的pagingSourceFactory中调用工厂的create方法,每次都会生成全新的PagingSource实例:
@HiltViewModel class YourViewModel @Inject constructor( private val pagingSourceFactory: ExamplePagingSourceFactory ) : ViewModel() { // 用StateFlow管理动态变化的查询参数 private val _currentQuery = MutableStateFlow("initial_query") val currentQuery = _currentQuery.asStateFlow() val flow = currentQuery.flatMapLatest { query -> Pager(PagingConfig(pageSize = 20)) { pagingSourceFactory.create(query) }.flow }.cachedIn(viewModelScope) // 搜索操作:更新query触发重新创建Pager和PagingSource fun onSearch(query: String) { _currentQuery.value = query } }
方案二:直接注入固定依赖+动态创建实例
如果不想使用AssistedInject,也可以在ViewModel中直接注入ExampleBackendService,然后在Pager的工厂方法里直接实例化PagingSource——这完全符合Hilt的使用逻辑,固定依赖由Hilt管理,动态参数按需传入,每次都生成新实例:
@HiltViewModel class YourViewModel @Inject constructor( private val backend: ExampleBackendService ) : ViewModel() { private val _currentQuery = MutableStateFlow("initial_query") val currentQuery = _currentQuery.asStateFlow() val flow = currentQuery.flatMapLatest { query -> Pager(PagingConfig(pageSize = 20)) { ExamplePagingSource(backend, query) }.flow }.cachedIn(viewModelScope) fun onSearch(query: String) { _currentQuery.value = query } }
为什么之前的setter方式不行?
Pager调用refresh()时,会重新执行你传入的pagingSourceFactory获取新实例。如果你复用同一个PagingSource对象仅修改query,Pager会检测到实例重复并抛出IllegalStateException——因为PagingSource内部维护了分页状态(如当前页码、加载状态),复用实例会导致状态混乱,因此Pager强制要求每次提供全新实例。
内容的提问来源于stack exchange,提问作者Abu Yousuf

