Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
alexacm2
architecture-components-samples
提交
95d22727
A
architecture-components-samples
项目概览
alexacm2
/
architecture-components-samples
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
architecture-components-samples
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
95d22727
编写于
4月 21, 2021
作者:
D
Dustin Lam
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add a sample showing how to synchronously await for remote loads to be applied
上级
8f4936b3
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
150 addition
and
3 deletion
+150
-3
PagingWithNetworkSample/app/src/main/java/com/android/example/paging/pagingwithnetwork/reddit/ui/RedditActivity.kt
...mple/paging/pagingwithnetwork/reddit/ui/RedditActivity.kt
+9
-3
PagingWithNetworkSample/lib/src/main/java/com/android/example/paging/pagingwithnetwork/reddit/paging/CombinedLoadStatesHelper.kt
...gingwithnetwork/reddit/paging/CombinedLoadStatesHelper.kt
+141
-0
未找到文件。
PagingWithNetworkSample/app/src/main/java/com/android/example/paging/pagingwithnetwork/reddit/ui/RedditActivity.kt
浏览文件 @
95d22727
...
...
@@ -31,6 +31,7 @@ import androidx.paging.LoadState
import
com.android.example.paging.pagingwithnetwork.GlideApp
import
com.android.example.paging.pagingwithnetwork.databinding.ActivityRedditBinding
import
com.android.example.paging.pagingwithnetwork.reddit.ServiceLocator
import
com.android.example.paging.pagingwithnetwork.reddit.paging.asHelperStates
import
com.android.example.paging.pagingwithnetwork.reddit.repository.RedditPostRepository
import
kotlinx.coroutines.flow.collect
import
kotlinx.coroutines.flow.collectLatest
...
...
@@ -85,7 +86,7 @@ class RedditActivity : AppCompatActivity() {
lifecycleScope
.
launchWhenCreated
{
adapter
.
loadStateFlow
.
collectLatest
{
loadStates
->
binding
.
swipeRefresh
.
isRefreshing
=
loadStates
.
refresh
is
LoadState
.
Loading
binding
.
swipeRefresh
.
isRefreshing
=
loadStates
.
mediator
?.
refresh
is
LoadState
.
Loading
}
}
...
...
@@ -97,10 +98,15 @@ class RedditActivity : AppCompatActivity() {
lifecycleScope
.
launchWhenCreated
{
adapter
.
loadStateFlow
// Only emit when REFRESH LoadState for RemoteMediator changes.
// Use a state-machine to track LoadStates such that we only transition to
// NotLoading from a RemoteMediator load if it was also presented to UI.
.
asHelperStates
()
// Only emit when REFRESH changes, as we only want to react on loads replacing the
// list.
.
distinctUntilChangedBy
{
it
.
refresh
}
// Only react to cases where R
emote R
EFRESH completes i.e., NotLoading.
// Only react to cases where REFRESH completes i.e., NotLoading.
.
filter
{
it
.
refresh
is
LoadState
.
NotLoading
}
// Scroll to top is synchronous with UI updates, even if remote load was triggered.
.
collect
{
binding
.
list
.
scrollToPosition
(
0
)
}
}
}
...
...
PagingWithNetworkSample/lib/src/main/java/com/android/example/paging/pagingwithnetwork/reddit/paging/CombinedLoadStatesHelper.kt
0 → 100644
浏览文件 @
95d22727
package
com.android.example.paging.pagingwithnetwork.reddit.paging
import
androidx.paging.CombinedLoadStates
import
androidx.paging.LoadState
import
androidx.paging.LoadState.*
import
androidx.paging.LoadStates
import
com.android.example.paging.pagingwithnetwork.reddit.paging.HelperState.*
import
kotlinx.coroutines.ExperimentalCoroutinesApi
import
kotlinx.coroutines.flow.Flow
import
kotlinx.coroutines.flow.scan
import
kotlin.Error
/**
* Track the combined [LoadState] of [RemoteMediator] and [PagingSource], so that each load type
* is only set to [NotLoading] when [RemoteMediator] load is applied on presenter-side.
*/
class
CombinedLoadStatesHelper
{
var
refresh
:
LoadState
=
NotLoading
(
endOfPaginationReached
=
false
)
private
set
var
prepend
:
LoadState
=
NotLoading
(
endOfPaginationReached
=
false
)
private
set
var
append
:
LoadState
=
NotLoading
(
endOfPaginationReached
=
false
)
private
set
private
var
refreshState
:
HelperState
=
NOT_LOADING
private
var
prependState
:
HelperState
=
NOT_LOADING
private
var
appendState
:
HelperState
=
NOT_LOADING
fun
toLoadStates
()
=
LoadStates
(
refresh
=
refresh
,
prepend
=
prepend
,
append
=
append
)
internal
fun
updateFromCombinedLoadStates
(
combinedLoadStates
:
CombinedLoadStates
)
{
computeHelperStates
(
sourceRefreshState
=
combinedLoadStates
.
source
.
refresh
,
sourceState
=
combinedLoadStates
.
source
.
refresh
,
remoteState
=
combinedLoadStates
.
mediator
?.
refresh
,
helperState
=
refreshState
,
).
also
{
refresh
=
it
.
first
refreshState
=
it
.
second
}
computeHelperStates
(
sourceRefreshState
=
combinedLoadStates
.
source
.
refresh
,
sourceState
=
combinedLoadStates
.
source
.
prepend
,
remoteState
=
combinedLoadStates
.
mediator
?.
prepend
,
helperState
=
prependState
,
).
also
{
prepend
=
it
.
first
prependState
=
it
.
second
}
computeHelperStates
(
sourceRefreshState
=
combinedLoadStates
.
source
.
refresh
,
sourceState
=
combinedLoadStates
.
source
.
append
,
remoteState
=
combinedLoadStates
.
mediator
?.
append
,
helperState
=
appendState
,
).
also
{
append
=
it
.
first
appendState
=
it
.
second
}
}
private
fun
computeHelperStates
(
sourceRefreshState
:
LoadState
,
sourceState
:
LoadState
,
remoteState
:
LoadState
?,
helperState
:
HelperState
,
):
Pair
<
LoadState
,
HelperState
>
{
if
(
remoteState
==
null
)
return
sourceState
to
NOT_LOADING
return
when
(
helperState
)
{
NOT_LOADING
->
when
(
remoteState
)
{
is
Loading
->
Loading
to
REMOTE_STARTED
is
Error
->
remoteState
to
REMOTE_ERROR
else
->
NotLoading
(
remoteState
.
endOfPaginationReached
)
to
NOT_LOADING
}
REMOTE_STARTED
->
when
{
remoteState
is
Error
->
remoteState
to
REMOTE_ERROR
sourceRefreshState
is
Loading
->
Loading
to
SOURCE_LOADING
else
->
Loading
to
REMOTE_STARTED
}
REMOTE_ERROR
->
when
(
remoteState
)
{
is
Error
->
remoteState
to
REMOTE_ERROR
else
->
Loading
to
REMOTE_STARTED
}
SOURCE_LOADING
->
when
{
sourceRefreshState
is
Error
->
sourceRefreshState
to
SOURCE_ERROR
remoteState
is
Error
->
remoteState
to
REMOTE_ERROR
sourceRefreshState
is
NotLoading
->
{
NotLoading
(
remoteState
.
endOfPaginationReached
)
to
NOT_LOADING
}
else
->
Loading
to
SOURCE_LOADING
}
SOURCE_ERROR
->
when
(
sourceRefreshState
)
{
is
Error
->
sourceRefreshState
to
SOURCE_ERROR
else
->
sourceRefreshState
to
SOURCE_LOADING
}
}
}
}
@OptIn
(
ExperimentalCoroutinesApi
::
class
)
fun
Flow
<
CombinedLoadStates
>.
asHelperStates
():
Flow
<
LoadStates
>
{
val
helper
=
CombinedLoadStatesHelper
()
return
scan
(
helper
.
toLoadStates
())
{
_
,
combinedLoadStates
->
helper
.
updateFromCombinedLoadStates
(
combinedLoadStates
)
helper
.
toLoadStates
()
}
}
/**
* State machine used to compute [LoadState] values in [CombinedLoadStatesHelper].
*/
enum
class
HelperState
{
/**
* Idle state; defer to remote state for endOfPaginationReached.
*/
NOT_LOADING
,
/**
* Remote load triggered; start listening for source refresh.
*/
REMOTE_STARTED
,
/**
* Waiting for remote in error state to get retried
*/
REMOTE_ERROR
,
/**
* Source refresh triggered by remote invalidation, once this completes we can be sure
* the next generation was loaded.
*/
SOURCE_LOADING
,
/**
* Remote load completed, but waiting for source refresh in error state to get retried.
*/
SOURCE_ERROR
,
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录