问题描述
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 { ... }
和 SearchRepositoriesActivityoverride suspend fun load(...)
都在主线程上运行。
分页2
根据documentation,viewmodel.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) {
...
}
}
}
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 中的主线程上运行。
PagingSource
解决方法
Kotlin协程
当使用Kotlin Coroutines实现PagingData
和PagingSource
并发出Retrofit网络请求时,如上面的示例代码中所示,Retrofit默认情况下处理后台线程并在主线程上返回。
请参阅StackOverflow:Does Retrofit make network calls on main thread?
RxJava
在将RxJava与Retrofit用作网络源时,需要明确指定线程,如Android文档样本中所示。
请参阅Android文档:Page from network and database> Implement a RemoteMediator