0
点赞
收藏
分享

微信扫一扫

利用安卓原生控件实现下拉刷新和上拉加载(SwipeRefreshLayout+Paging)

_LEON_ 2022-02-27 阅读 63


简要介绍

现在网上有各种下拉刷新控件,各种炫酷(如:SmartRefreshLayout).不过如果没有特别要求时,官方的控件就够用了,关键时,稳定,还好用.


  1. SwipeRefreshLayout 用于实现下拉刷新
  2. Paging 用于实现自动上拉加载数据,完全不用在activity中操心下一页加载的烦心事.


实现效果

主要实现代码(完整代码见Demo源代码)

  1. UserActivity.kt
class UserActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
val viewModel = obtainViewModel(UserViewModel::class.java)
val adapter = UserAdapter()
userRv.adapter = adapter
viewModel.userList.observe(this, Observer { adapter.submitList(it) })

//设置下拉刷新转圈的颜色
// swipeRefreshLayout.setColorSchemeColors(Color.RED,Color.BLUE,Color.GREEN)
swipeRefreshLayout.setOnRefreshListener {
viewModel.deleteAll()
viewModel.initData()
swipeRefreshLayout.isRefreshing = false
}
}
}
  1. activity_user.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/userRv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
  1. UserAdapter.kt
class UserAdapter : PagedListAdapter<User, UserAdapter.ViewHolder>(UserDiffCallback()) {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val data = getItem(position) ?: return
holder.itemView.userTv.text = data.name
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_user, parent, false)
return ViewHolder(view)
}

class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!)
}

private class UserDiffCallback : DiffUtil.ItemCallback<User>() {
override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.id == newItem.id
}

override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}
}
  1. UserViewModel.kt
class UserViewModel internal constructor(private val userRepository: UserRepository) : ViewModel() {
val userList = userRepository.getUserList()
fun deleteAll()
{
GlobalScope.launch {
userRepository.deleteAll()
}
}
fun initData() {
GlobalScope.launch {
(1..1000).forEach {
userRepository.addUser("user$it")
}
}
}
}
  1. ViewModelFactory.kt
class ViewModelFactory private constructor(
private val userRepository: UserRepository
) : ViewModelProvider.NewInstanceFactory() {

@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T =
with(modelClass) {
when {
isAssignableFrom(UserViewModel::class.java) -> {
UserViewModel(userRepository)
}
else ->
throw IllegalArgumentException("Unknown ViewModel: ${modelClass.name}")
}

} as T


companion object {
private var INSTANCE: ViewModelFactory? = null

fun getInstance() =
INSTANCE ?: synchronized(ViewModelFactory::class.java) {
INSTANCE ?: ViewModelFactory(
InjectionUtil.getUserRepository()
)
}
}
}
  1. UserRepository.kt
class UserRepository private constructor(private val userDao: UserDao) {

fun getUserList() = userDao.getUserList().toLiveData(
Config(
pageSize = 30,
enablePlaceholders = true
)
)

suspend fun addUser(name: String) {
withContext(Dispatchers.IO) {
val user = User(0, name)
userDao.add(user)
}
}

suspend fun deleteAll() {
withContext(Dispatchers.IO) {
userDao.deleteAll()
}
}

companion object {
@Volatile
private var instance: UserRepository? = null

fun getInstance(userDao: UserDao) =
instance ?: synchronized(this) {
instance
?: UserRepository(userDao).also { instance = it }
}
}
}

Demo源代码

https://gitee.com/cxyzy1/pullRefreshDemo

更多技术总结好文,请关注:「程序园中猿」



举报

相关推荐

0 条评论