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

Android Room PageSource<Key, Value>无数据加载问题求助

问题排查与修复方案

1. 先排查基础数据与查询逻辑问题

你的Dao查询使用了INNER JOIN,这意味着只有存在对应contact_message记录的联系人会被返回。如果数据库里有联系人但没有对应的消息记录,这些联系人会被直接过滤,导致无数据显示。

同时,查询中contact_message.message_body未使用聚合逻辑,在SQLite中这种写法虽然允许,但返回的latest_message_body是不确定的(通常取分组后第一条匹配的记录),可能导致查询逻辑异常。

修复SQL查询:

将INNER JOIN改为LEFT JOIN,确保无消息的联系人也能被返回;同时用子查询正确获取最新的消息内容:

@Query(
    """
SELECT 
    contact.id,
    contact.name,
    contact.number,
    MAX(contact_message.message_time) AS latest_message_time,
    COUNT(contact_message.id) as messages_count,
    (SELECT message_body FROM contact_message WHERE contact_id = contact.id ORDER BY message_time DESC LIMIT 1) AS latest_message_body
FROM
    contact
LEFT JOIN
    contact_message
ON
    contact_message.contact_id = contact.id
GROUP BY
    contact.id
ORDER BY
    latest_message_time DESC;
    """
)
fun getAllWithPagination(): PagingSource<Int, ContactWithCount>

2. 修复UI代码的语法错误

你的Compose代码存在明显笔误:index -应该是index ->,这个错误会导致Lambda无法正确执行,自然不会渲染任何列表项:

@OptIn(ExperimentalPagingApi::class)
@Composable
fun ContactsList(vm: SmsViewModel = viewModel()) {
    val pager = vm.getAllContactsPager().collectAsLazyPagingItems()
    LazyColumn(modifier = Modifier.fillMaxSize()) {
        items(
            count = pager.itemCount
        ) { index -> // 修正此处的 "-" 为 "->"
            val item = pager[index]
            item?.let {
                ContactBasicInfoCard(vm = vm, contactWithCount = item)
            }
        }
        // 添加加载状态提示,方便排查问题
        when (pager.loadState.refresh) {
            is LoadState.Loading -> item { 
                CircularProgressIndicator(modifier = Modifier.fillMaxWidth().padding(16.dp)) 
            }
            is LoadState.Error -> item { 
                Text("加载失败:${(pager.loadState.refresh as LoadState.Error).error.message}", 
                     modifier = Modifier.padding(16.dp)) 
            }
            else -> Unit
        }
    }
}

3. 验证ViewModel的正确性

你的ViewModel代码类名为SomeClass,但UI中使用的是SmsViewModel,这会导致UI获取的ViewModel实例没有getAllContactsPager方法,自然无法获取数据。需要修正ViewModel类名,并确保注入数据库实例:

class SmsViewModel(private val db: YourDatabaseInstance) : ViewModel() {
    @ExperimentalPagingApi
    fun getAllContactsPager(): Flow<PagingData<ContactWithCount>> {
        return Pager(
            config = PagingConfig(pageSize = 20),
        ) {
            db.contactDao().getAllWithPagination()
        }.flow.cachedIn(viewModelScope)
    }
}

4. 额外排查步骤

  • 验证数据库数据:用Android Studio的Database Inspector查看contact和contact_message表,确认存在符合条件的记录。
  • 打印日志验证Paging数据:在ViewModel中添加日志,确认Flow是否返回数据:
    viewModelScope.launch {
        getAllContactsPager().collect { pagingData ->
            pagingData.map { Log.d("PagingDebug", "联系人:${it.name}") }
        }
    }
    
  • 检查依赖兼容性:确保Room版本≥2.3.0,Paging3版本与Jetpack其他组件版本匹配(比如androidx.paging:paging-compose:3.2.1对应androidx.room:room-runtime:2.5.0左右)。

内容的提问来源于stack exchange,提问作者Seyed Hussein Mirzaki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:14:55