PagingData库中默认情况下是否在后台线程上运行PagingData?

问题描述

private void displayGame(){ printMap(2,2); } public void printMap(int playerPositionX,int playerPositionY) { System.out.println(); boolean foundRow = false; boolean foundPosition = false; for (int i = 0; i < map.length; i++){ System.out.print("|"); if (!foundRow && playerPositionY == i){ foundRow = true; } for (int k = 0; k < map[i].length; k++){ if (foundRow && (playerPositionX == k)){ foundPosition = true; } if (i == 0) { System.out.print("-"); }else if (i == map.length-1){ System.out.print("_"); }else if (foundPosition){ System.out.print("^"); foundPosition = false; foundRow = false; }else { System.out.print(" "); } } System.out.println("|"); } } 会像PagingData一样自动管理后台线程,然后在主线程上返回吗?

从下面的日志中可以看出,与分页2的库中的PagedList相比,分页3的库中的PagingData不在后台线程上运行。

期望基于Paging Codelab示例

  • GithubPagingSource PagedList可以在IO线程上运行。
  • SearchRepositoriesActivity override suspend fun load(...)在主线程上运行。

观察

  • GithubPagingSource viewmodel.searchRepo(query).collectLatest { ... } SearchRepositoriesActivity override suspend fun load(...)都在主线程上运行。

分页2

根据documentationviewmodel.searchRepo(query).collectLatest { ... }PagedList在后​​台处理线程。

如果您使用LivePagedListBuilder来获取LiveData,它将为您在后台线程上初始化PagedLists。

分页3

分页3 documentation没有提到如何管理线程。但是,从日志中,toLiveData似乎正在主线程上运行网络请求,并在主线程上返回了PagingSource

我的示例代码

我已经在CryptoTweets示例应用程序 app-simple 模块中重新创建了Codelab模式。

FeedPagingSource.kt

PagingData

FeedRepository.kt

class FeedPagingSource : PagingSource<Int,Tweet>() {

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int,Tweet> {
        try {
            val page = params.key ?: 1
            val nextPage = page + 1
            val tweets = Injection.FeedService.getTweets(...)
            println("Thread: FeedPagingSource ${Thread.currentThread().name}")
            Log.v(LOG_TAG,"load success: ${tweets}")
            return LoadResult.Page(...)
        } catch (error: Exception) {
            ...
        }
    }
}

Feedviewmodel.kt

class FeedRepository {
    fun initFeed() = Pager(
        config = PagingConfig(pageSize = Feed_PAGEDLIST_SIZE),pagingSourceFactory = { FeedPagingSource() }
    ).flow
}

尝试的解决方

为了在后台线程上运行repository.initFeed().onEach { println("Thread: Feedviewmodel ${Thread.currentThread().name}") _Feed.value = it }.launchIn(viewmodelScope) ,该流程在PagingSource上启动。但是,日志仍然显示dispatchers.IO FeedPagingSource.kt 中的主线程上运行。

Feedviewmodel.kt

PagingSource

解决方法

Kotlin协程

当使用Kotlin Coroutines实现PagingDataPagingSource并发出Retrofit网络请求时,如上面的示例代码中所示,Retrofit默认情况下处理后台线程并在主线程上返回。

请参阅StackOverflow:Does Retrofit make network calls on main thread?

RxJava

在将RxJava与Retrofit用作网络源时,需要明确指定线程,如Android文档样本中所示。

请参阅Android文档:Page from network and database> Implement a RemoteMediator