![](yasha.png)

# Yasha 一个渲染RecyclerView和ViewPager以及ComposeList的DSL库. > *Read this in other languages: [中文](README.zh.md), [English](README.md), [Changelog](CHANGELOG.md)* ## 功能介绍: ✅ 支持RecyclerView ✅ 支持ViewPager ✅ 支持MultiType ✅ 支持Header和Footer ✅ 支持自动分页加载 ✅ 支持DiffUtils刷新 ✅ 支持加载状态显示 ✅ 支持CleanUp自动清理资源 ✅ 支持Compose ![](yasha_usage.png) ## Prepare 1. 添加jitpack到build.gradle ```gradle allprojects { repositories { maven { url 'https://jitpack.io' } } } ``` 2. 添加依赖 ```gradle dependencies { implementation 'com.github.ssseasonnn:Yasha:1.2.0' // or implementation 'com.github.ssseasonnn.Yasha:yasha:1.2.0' //only for recyclerview implementation 'com.github.ssseasonnn.Yasha:yasha-compose:1.2.0' //only for compose } ``` ## 基本用法 ### 1. 渲染RecyclerView ```kotlin //创建数据类 class RecyclerViewItem(val i: Int, val text: String = "") : YashaItem //创建DataSource val dataSource = YashaDataSource() //渲染RecyclerView recyclerView.linear(dataSource) { renderBindingItem { onBind { itemBinding.tvNormalContent.text = "position: $position, data: $data" } } } ``` ### 2. 渲染ViewPager ```kotlin //创建数据类 class ViewPagerItem(val i: Int, val text: String = "") : YashaItem //创建DataSource val dataSource = YashaDataSource() //渲染ViewPager viewPager.vertical(dataSource) { renderBindingItem { onBind { itemBinding.tvNormalContent.text = "position: $position, data: $data" } } } ``` ## 其余配置 ### 1. 渲染类型 Yasha支持多种类型的RecyclerView,如列表、Grid、Stagger以及Pager和自定义列表类型 ```kotlin //渲染列表 recyclerView.linear(dataSource) { //设置方向为垂直列表或横向列表 orientation(RecyclerView.VERTICAL) renderBindingItem {} } //渲染表格 recyclerView.grid(dataSource) { //设置列数量 spanCount(2) renderBindingItem { //设置该item项对应的列数 gridSpanSize(2) onBind {} } } //渲染瀑布流 recyclerView.stagger(dataSource) { //设置列数量 spanCount(2) renderBindingItem { staggerFullSpan(true) onBind {} } } //渲染Page recyclerView.pager(dataSource) { //注册翻页回调 onPageChanged { position, yashaItem, view -> Toast.makeText(this, "This is page $position", Toast.LENGTH_SHORT).show() } } //渲染自定义layout recyclerView.custom(customLayoutManager, dataSource) {} ``` ### 2. DataSource分页加载 ```kotlin // 继承YashaDataSource并重写**loadInitial**和**loadAfter**方法即可 class CustomDataSource(coroutineScope: CoroutineScope) : YashaDataSource(coroutineScope) { var page = 0 // 初始化加载时调用,位于IO线程 override suspend fun loadInitial(): List? { page = 0 val items = mutableListOf() for (i in 0 until 10) { items.add(NormalItem(i)) } // 返回null触发加载失败 // 返回空列表触发没有更多 return items } // 分页加载时调用,位于IO线程 override suspend fun loadAfter(): List? { page++ //模拟加载失败 if (page % 5 == 0) { // 返回null触发加载失败 return null } val items = mutableListOf() for (i in 0 until 10) { items.add(NormalItem(i)) } // 返回空列表触发没有更多 return items } } ``` ### 3. 渲染MultiType ```kotlin //定义数据类型A class AItem(val i: Int) : YashaItem //定义数据类型B class BItem(val i: Int) : YashaItem //渲染Item recyclerView.linear(dataSource) { //渲染类型 A renderBindingItem { onBind { //render ... } } //渲染类型 B renderBindingItem { onBind { //render ... } } } ``` ### 4. Header 和 Footer DataSource支持以下多种添加Header和Footer的方法: ```kotlin //Headers fun addHeader(t: T, position: Int = -1, delay: Boolean = false) fun addHeaders(list: List, position: Int = -1, delay: Boolean = false) fun removeHeader(t: T, delay: Boolean = false) fun setHeader(old: T, new: T, delay: Boolean = false) fun getHeader(position: Int): T fun clearHeader(delay: Boolean = false) //Footers fun addFooter(t: T, position: Int = -1, delay: Boolean = false) fun addFooters(list: List, position: Int = -1, delay: Boolean = false) fun removeFooter(t: T, delay: Boolean = false) fun setFooter(old: T, new: T, delay: Boolean = false) fun getFooter(position: Int): T fun clearFooter(delay: Boolean = false) ``` ### 5. 局部刷新 通过重写数据类的Diff方法,即可完成高效的局部刷新 ```kotlin //定义数据类型时,重写Diff方法 class NormalItem(val i: Int, val text: String = "") : YashaItem { override fun areItemsTheSame(other: Differ): Boolean { if (other !is NormalItem) return false return other.i == i } override fun areContentsTheSame(other: Differ): Boolean { if (other !is NormalItem) return false return other.text == text } //设置payload override fun getChangePayload(other: Differ): Any? { if (other !is NormalItem) return null return other.text } } //dataSource更新新的Item数据 val oldItem = NormalItem(1, "1") val newItem = NormalItem(2, "2") dataSource.setItem(oldItem, newItem) // 渲染时注册onBindPayload recyclerView.linear(dataSource) { renderBindingItem { onBind { itemBinding.tvNormalContent.text = "position: $position, data: $data" } //局部刷新使用 onBindPayload { //取出payload进行局部刷新 val payload = it[0] if (payload != null) { itemBinding.tvNormalContent.text = payload.toString() } } } } ``` ### 6. 自定义加载状态 ```kotlin //使用默认的加载状态 val dataSource = YashaDataSource(enableDefaultState = true) //自定义加载状态 class CustomStateItem(val state: Int) : YashaItem class CustomDataSource : YashaDataSource(enableDefaultState = false) { override fun onStateChanged(newState: Int) { setState(CustomStateItem(newState)) } } //渲染自定义状态 recyclerView.linear(dataSource) { ... renderBindingItem { onBind { when (data.state) { FetchingState.FETCHING -> { //加载中 } FetchingState.FETCHING_ERROR -> { //加载失败 } FetchingState.DONE_FETCHING -> { //加载完成 } else -> { //其他 } } } } } ``` ### 7. 混淆 仅当使用反射创建ViewBinding时,需要添加以下proguard rule: ```pro -keepclassmembers class * implements androidx.viewbinding.ViewBinding { public static ** inflate(...); } ``` ## License > ``` > Copyright 2021 Season.Zlc > > Licensed under the Apache License, Version 2.0 (the "License"); > you may not use this file except in compliance with the License. > You may obtain a copy of the License at > > http://www.apache.org/licenses/LICENSE-2.0 > > Unless required by applicable law or agreed to in writing, software > distributed under the License is distributed on an "AS IS" BASIS, > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. > See the License for the specific language governing permissions and > limitations under the License. > ```