Android Compose list 下拉刷新、上拉加载更多
前言:本文使用UI框架Compose +Paging+Swiperefresh实现列表的下拉刷新,上拉加载更多功能
一、添加相关库包括viewModel ,Paging,Swiperefresh的Compose库
implementation ("androidx.emoji2:emoji2:1.3.0")
//network & serialization
implementation ("com.google.code.gson:gson:2.9.0")
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
implementation ("com.squareup.retrofit2:retrofit:2.9.0")//
implementation ("com.squareup.okhttp3:logging-interceptor:4.9.3")
//swiperefresh 的compose 版本
implementation ("com.google.accompanist:accompanist-swiperefresh:0.30.1")
// paging 3 的compose 版本
implementation ("androidx.paging:paging-compose:1.0.0-alpha18")
//这个可以在Compose中得到viewmodel
implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
//coil Compose 图片加载库
implementation ("io.coil-kt:coil-compose:2.0.0-rc01")
二、MainActivity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeDemoTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
ListContent()
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
ComposeDemoTheme {
Greeting("Android")
}
}
@Composable
fun ListContent(){
val viewModel:GithubViewModel= viewModel()
val lazyPagingItems=viewModel.repositorPager.collectAsLazyPagingItems()
val state:LazyListState= rememberLazyListState()
SwipeRefresh(state =rememberSwipeRefreshState(lazyPagingItems.loadState.refresh is LoadState.Loading&&lazyPagingItems.itemCount > 0) ,
onRefresh = { lazyPagingItems.refresh() }) {
LazyColumn(state =state,
contentPadding = PaddingValues(10.dp),
verticalArrangement = Arrangement.SpaceEvenly){
items(items=lazyPagingItems){item->
item?.let {
RepositorCard(it)
}
}
if(lazyPagingItems.loadState.append is LoadState.Loading){
item {
Box(modifier = Modifier
.fillMaxWidth()
.height(50.dp)){
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}
}
}
if(lazyPagingItems.loadState.refresh is LoadState.Loading){
if(lazyPagingItems.itemCount==0){
Box(modifier = Modifier.fillMaxSize()) {
CircularProgressIndicator(modifier = Modifier.align(alignment = Alignment.Center))
}
}
}else if(lazyPagingItems.loadState.refresh is LoadState.Error){
//加载失败的错误页面
Box(modifier = Modifier.fillMaxSize()) {
Button(modifier = Modifier.align(alignment = Alignment.Center),
onClick = { lazyPagingItems.refresh() }) {
Text(text = "加载失败!请重试")
}
}
}
}
}
@Composable
fun RepositorCard(repositorItem: RepositorItem) {
Card(modifier = Modifier
.fillMaxWidth()
.padding(8.dp)) {
Row(modifier = Modifier
.fillMaxWidth()
.height(88.dp)) {
Spacer(modifier = Modifier.width(10.dp))
Surface(shape = CircleShape, modifier = Modifier
.size(66.dp)
.align(Alignment.CenterVertically)) {
AsyncImage(model = repositorItem.owner.avatar_url,
contentDescription = "",
contentScale = ContentScale.Crop)
}
Spacer(modifier = Modifier.width(15.dp))
Column(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.height(8.dp))
Text(text = repositorItem.name,
)
Text(text = repositorItem.full_name, style = MaterialTheme.typography.bodyMedium)
}
}
}
}
三、MyPagingSource
class MyPagingSource(
val githubService: GithubService = getGithubService(),
val words: String,
) : PagingSource<Int, RepositorItem>() {
override fun getRefreshKey(state: PagingState<Int, RepositorItem>): Int? {
return state.anchorPosition?.let {
val anchorPage = state.closestPageToPosition(it)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, RepositorItem> {
try {
val nextPage: Int = params.key ?: 1
val repositorRst = githubService.searchRepositors(words, nextPage, 20)
return LoadResult.Page(
data = repositorRst.items,
prevKey = if (nextPage == 1) null else nextPage - 1,
nextKey = if (repositorRst.items.isEmpty()) null else nextPage + 1
)
}catch (e:Exception){
return LoadResult.Error(e)
}
}
四、GithubViewModel
class GithubViewModel:ViewModel() {
val repositorPager = Pager(config = PagingConfig(pageSize = 6)){
MyPagingSource(getGithubService(),"compose")
}.flow.cachedIn(viewModelScope)
}
Demo下载:https://download.csdn.net/download/ange_li/90152118