kotlin 整合RecyclerView 上拉刷新 下拉加载更多

使用代码如下

RefreshListView(refreshLayout,recyclerView).apply {
     recyclerView.layoutManager = LinearLayoutManager(this@RecyclerViewTestActivity)
     onProcess = {
        RetrofitServiceManager.create(PosApi::class.java).getList(page,pageSize).get()
     }
     register(String::class.java,R.layout.test_item){holder, data ->
        (holder[R.id.textView] as TextView).text = data
      }
}

代码构建如下

//加载更多的滑动监听
abstract class onLoadMoreListener : RecyclerView.OnScrollListener() {
    private var countItem = 0
    private var lastItem = 0
    private var isScolled = false //是否可以滑动
    private var layoutManager: RecyclerView.LayoutManager? = null

    /**
     * 加载回调方法
     * @param countItem 总数量
     * @param lastItem  最后显示的position
     */
    protected abstract fun onLoading(countItem: Int, lastItem: Int)
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        //拖拽或者惯性滑动时isScolled设置为true
        isScolled = newState == RecyclerView.SCROLL_STATE_DRAGGING || newState == RecyclerView.SCROLL_STATE_SETTLING
    }

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        if (recyclerView.layoutManager is LinearLayoutManager) {
            layoutManager = recyclerView.layoutManager
            countItem = layoutManager!!.itemCount
            lastItem =  (layoutManager as LinearLayoutManager?)!!.findLastCompletelyVisibleItemPosition()
        }
        if (isScolled && countItem != lastItem && lastItem == countItem - 1) {
            onLoading(countItem, lastItem)
        }
    }
}
//每项不同类型的视图实体
data  class ItemBindView<T:Any>(val itemLayout:Int,val setItemValue: ((holder: JsonViewHolder, data: T) -> Unit)?)
//默认的下拉视图类型
class FotterItem()
//返回的数据对象
class ListData{
    var count:Int = 0
    var data:MutableList<Any> = mutableListOf()
}
//上拉,下拉初始化类
class RefreshListView(val refreshLayout: SwipeRefreshLayout,val recyclerView:RecyclerView){
    var pageSize = 20
    var page = 1
    var count = 0
    var datas:MutableList<Any> = mutableListOf()
    var onBefor:((isRefresh:Boolean)->Unit)? = null
    var onProcess:((isRefresh:Boolean)->ListData)? = null
    var onComplet:((isRefresh:Boolean)->Unit)? = null

    val context:Context = recyclerView.context
    private var registers:MutableMap<Any,Any> = mutableMapOf()
    private var types:MutableList<Any> = mutableListOf()
    private fun notifyDataSetChanged(){
        recyclerView.adapter?.notifyDataSetChanged()
    }

    init {
        //下拉刷新的圆圈是否显示
        refreshLayout.apply {
            isRefreshing = false
            setColorSchemeResources(
                android.R.color.holo_blue_light,
                android.R.color.holo_red_light,
                android.R.color.holo_orange_light
            )
            setProgressBackgroundColorSchemeResource(android.R.color.white)
            setOnRefreshListener {
                start(true)

            }
        }
        recyclerView.apply {
            addOnScrollListener(object : onLoadMoreListener() {
                override fun onLoading(countItem: Int, lastItem: Int) {
                    if (page * pageSize < count) {
                       start(false)
                    }
                }
            })
            adapter = object : RecyclerView.Adapter<JsonViewHolder>() {
                override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JsonViewHolder {
                    val itemBindView = itemBindView(viewType)
                    val view: View =
                        LayoutInflater.from(context).inflate(itemBindView.itemLayout, parent, false)
                    return JsonViewHolder(view)
                }

                override fun getItemCount(): Int {
                    return datas.size
                }
                /**
                 * 获取itemBindView
                 */
                private fun itemBindView(viewType: Int): ItemBindView<Any> {
                    val clas = types[viewType]
                    val itemBindView = registers[clas] as ItemBindView<Any>
                    return itemBindView
                }

                override fun onBindViewHolder(holder: JsonViewHolder, position: Int) {
                    if(position == 19){
                        Log.i("xiaochangyan",position.toString())
                    }


                    val itemBindView = itemBindView(getItemViewType(position))
                    val json = datas[position]
                    if(JSON.toJSON(json) is JSONObject)
                    holder.initJsonValue(JSON.toJSON(json) as JSONObject)
                    itemBindView.setItemValue?.invoke(holder, json)
                }

                override fun getItemViewType(position: Int): Int {
                    val data = datas[position]
                    val clas = data::class.java
                    return types.indexOf(clas)
                }
            }
        }
        register(FotterItem::class.java,R.layout.foot_layout,null)
    }
    private fun start(isRefresh: Boolean){
        onBefor?.invoke(isRefresh)
        //更正页脚
        if(isRefresh){
            page = 1
        }else{
            page+=1
        }
        GlobalScope.launch(Dispatchers.IO){
            var list:ListData? = null
            try {
                list = onProcess?.invoke(isRefresh)
            }catch (e:java.lang.Exception){
                e.printStackTrace()
            }
            withContext(Dispatchers.Main){
                refreshLayout.isRefreshing = false
                list?.let {
                    count = it.count//设置记录条数
                    if(isRefresh){
                        datas.clear()
                    }else{
                        if(datas.last() is FotterItem){
                            datas.removeAt(datas.lastIndex)
                        }
                    }
                    datas.addAll(it.data)
                    if (page * pageSize < count) {
                        datas.add(FotterItem())
                    }
                    notifyDataSetChanged()
                }
                onComplet?.invoke(isRefresh)
            }
        }
    }
    fun <T:Any> register(clas:Class<T>,itemLayout:Int,setItemValue: ((holder: JsonViewHolder, data: T) -> Unit)?){
        registers[clas] = ItemBindView(itemLayout,setItemValue)
        types.add(clas)
    }
}
/**
 * 统一一个以json为实体的ViewHolder
 */
class JsonViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    val map = mutableMapOf<String, View?>()
    operator fun get(id:Int): View?{
        if(map.containsKey(id.toString())){
            return map[id.toString()]
        }
        val view = itemView.findViewById<View?>(id)
        map[id.toString()] = view
        return view
    }
    operator fun get(tag:String): View?{
        if(map.containsKey(tag)){
            return map[tag]
        }
        val view = itemView.findViewWithTag<View?>(tag) ?: return null
        map[tag] = view
        return view
    }

    operator fun set(tag:String,value:String){
        val view: View = this[tag] ?: return
        when{
            view is TextView -> view.text = value
            view is EditText -> view.setText(value)
        }
    }
    fun initJsonValue(jsonObject: JSONObject){
        for (key in jsonObject.keys){
            if(this[key] ==null)continue
            this[key] = when{jsonObject[key]==null->"" else ->jsonObject[key].toString()}
        }
    }
}
/**
 * 简单的适配器扩展
 */
fun RecyclerView.initAdapter(list: JSONArray, layout:Int, setItemValue: ((holder: JsonViewHolder, data: JSONObject) -> Unit)?){
    this.adapter = object :RecyclerView.Adapter<JsonViewHolder>(){
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JsonViewHolder {
            val view: View = LayoutInflater.from(this@initAdapter.context).inflate(layout, parent, false)
            return JsonViewHolder(view)
        }
        override fun getItemCount(): Int {
            return list.size
        }
        override fun onBindViewHolder(holder: JsonViewHolder, position: Int) {
            val json = list.getJSONObject(position)
            holder.initJsonValue(json)
            setItemValue?.invoke(holder,json)
        }
    }
}

/**
 * 简单的适配器扩展
 */
fun <T> RecyclerView.initAdapter(list: MutableList<T>, layout:Int, setItemValue: ((holder: JsonViewHolder, data: T) -> Unit)?){
    this.adapter = object :RecyclerView.Adapter<JsonViewHolder>(){
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JsonViewHolder {
            val view: View = LayoutInflater.from(this@initAdapter.context).inflate(layout, parent, false)
            return JsonViewHolder(view)
        }
        override fun getItemCount(): Int {
            return list.size
        }
        override fun onBindViewHolder(holder: JsonViewHolder, position: Int) {
            val json = list.get(position)
            holder.initJsonValue(JSON.toJSON(json) as JSONObject)
            setItemValue?.invoke(holder,json)
        }
    }
}
fun RecyclerView.notifyDataSetChanged(){
    this.adapter?.notifyDataSetChanged()
}

其他资源

//api
@GET("WGHQ.PayTest/CYPosApi/getList")
fun getList(@Query("page")page:Int,@Query("pageSize")pageSize:Int):Deferred<ListData>
//itemLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="50dp"/>
    <View style="@style/MMViewLine"/>
</LinearLayout>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352