礼品兑换网站怎么做陕西百度推广的代理商
为了简化 Jetpack Paging 的使用并提升代码的可维护性,可以对其进行封装,提供一个通用的分页加载工具类。以下是优化后的封装方案,支持与 Room 数据库、网络数据源的集成,并提供简洁的 API。
1. 封装思路
通用 PagingSource:封装通用的分页数据加载逻辑,支持 Room 和网络数据源。
PagingHelper:提供分页数据的创建和管理。
Repository 和 ViewModel 集成:通过简洁的 API 实现分页数据的加载和显示。
2. 封装代码
2.1 添加依赖
在 build.gradle 中添加 Paging 和 Room 依赖:
dependencies {def paging_version = "3.2.1"implementation "androidx.paging:paging-runtime:$paging_version"implementation "androidx.paging:paging-compose:$paging_version" // 如果使用 Jetpack Composeimplementation "androidx.room:room-ktx:2.6.1" // Room 支持
}
2.2 定义通用 PagingSource
封装通用的分页数据加载逻辑:
import androidx.paging.PagingSource
import androidx.paging.PagingStateabstract class BasePagingSource<Key : Any, Value : Any> : PagingSource<Key, Value>() {abstract suspend fun loadData(params: LoadParams<Key>): LoadResult<Key, Value>override suspend fun load(params: LoadParams<Key>): LoadResult<Key, Value> {return try {loadData(params)} catch (e: Exception) {LoadResult.Error(e)}}override fun getRefreshKey(state: PagingState<Key, Value>): Key? {return state.anchorPosition?.let { anchorPosition ->state.closestPageToPosition(anchorPosition)?.prevKey?: state.closestPageToPosition(anchorPosition)?.nextKey}}
}
2.3 定义 PagingHelper
封装分页数据的创建和管理:
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flowclass PagingHelper<Key : Any, Value : Any>(private val pagingSourceFactory: () -> PagingSource<Key, Value>,private val pageSize: Int = 20,private val enablePlaceholders: Boolean = false
) {fun getPagingData(): Flow<PagingData<Value>> {return Pager(config = PagingConfig(pageSize = pageSize,enablePlaceholders = enablePlaceholders),pagingSourceFactory = pagingSourceFactory).flow}
}
2.4 定义 Repository
在 Repository 中使用 PagingHelper 创建分页数据流:
class UserRepository(private val userDao: UserDao) {fun getUsers(): Flow<PagingData<User>> {val pagingHelper = PagingHelper<Int, User>(pagingSourceFactory = { userDao.getUsers() })return pagingHelper.getPagingData()}
}
2.5 定义 ViewModel
在 ViewModel 中观察分页数据:
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import androidx.paging.cachedIn
import kotlinx.coroutines.flow.Flowclass UserViewModel(private val repository: UserRepository) : ViewModel() {val users: Flow<PagingData<User>> = repository.getUsers().cachedIn(viewModelScope) // 缓存数据,避免重复加载
}
2.6 在 Activity/Fragment 中绑定数据
使用 PagingDataAdapter 在 RecyclerView 中显示分页数据:
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtilclass MainActivity : AppCompatActivity() {private val viewModel: UserViewModel by viewModels()private lateinit var adapter: UserAdapteroverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)adapter = UserAdapter()recyclerView.adapter = adapter// 观察分页数据viewModel.users.observe(this) { pagingData ->adapter.submitData(lifecycle, pagingData)}}
}class UserAdapter : PagingDataAdapter<User, UserViewHolder>(USER_COMPARATOR) {override fun onBindViewHolder(holder: UserViewHolder, position: Int) {val user = getItem(position)user?.let { holder.bind(it) }}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {return UserViewHolder.create(parent)}companion object {private val USER_COMPARATOR = object : DiffUtil.ItemCallback<User>() {override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {return oldItem.id == newItem.id}override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {return oldItem == newItem}}}
}
2.7 支持网络数据源
如果需要从网络加载数据,可以自定义 PagingSource:
class UserPagingSource(private val apiService: ApiService) : BasePagingSource<Int, User>() {override suspend fun loadData(params: LoadParams<Int>): LoadResult<Int, User> {val page = params.key ?: 1val response = apiService.getUsers(page, params.loadSize)return LoadResult.Page(data = response.users,prevKey = if (page == 1) null else page - 1,nextKey = if (response.users.isEmpty()) null else page + 1)}
}
在 Repository 中使用:
class UserRepository(private val apiService: ApiService) {fun getUsers(): Flow<PagingData<User>> {val pagingHelper = PagingHelper<Int, User>(pagingSourceFactory = { UserPagingSource(apiService) })return pagingHelper.getPagingData()}
}
3. 封装的优势
通用性:通过 BasePagingSource 和 PagingHelper,支持 Room 和网络数据源。
简洁性:提供简洁的 API,减少重复代码。
高性能:支持协程和 Flow,确保线程安全和高效加载。
易扩展:支持自定义 PagingSource 和 RemoteMediator,适用于复杂场景。
4. 进一步优化
4.1 支持依赖注入
结合 Dagger/Hilt,进一步解耦依赖:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {@Provides@Singletonfun provideUserRepository(userDao: UserDao): UserRepository {return UserRepository(userDao)}
}
4.2 支持边界回调
通过 RemoteMediator 实现网络和本地数据库的混合分页加载。
5. 总结
通过封装 Jetpack Paging,可以显著简化分页加载的实现,提升代码的可维护性和扩展性。关键点包括:
使用 BasePagingSource 封装通用分页逻辑。
使用 PagingHelper 简化分页数据的创建。
结合 Room 和网络数据源,提供灵活的分页加载方案。
这套封装方案适用于大多数 Android 项目,能够显著提升开发效率和代码质量。