Kotlin-based modern RecyclerView rendering weapon

Overview

Read this in other languages: 中文, English, Changelog

Yasha

Item introduction:

Kotlin-based modern RecyclerView rendering weapon

Item Features:

  • No Adapter required
  • No ViewHolder required
  • Support Coroutine
  • Support page loading
  • Support for MultiViewType
  • Support for Header and Footer
  • Support DiffUtil
  • Support Loading State
  • Support CleanUp, free resources to avoid memory leaks

Prepare

  1. Add jitpack to build.gradle
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  1. Add dependency
dependencies {
	implementation 'com.github.ssseasonnn:Yasha:1.1.0'
}

First Blood

How to quickly render a RecyclerView? Still tirelessly writing Adapter, ViewHolder? Let Yasha come to save you:

  //Render a list with ** dataSource ** as the data source
  recycler_view.linear(dataSource) {

      //Render an Item of type NormalItem
      renderItem<NormalItem> {
          //layout res
          res(R.layout.view_holder_normal)

          //bind data 
          onBind {
              tv_normal_content.text = data.toString()
          }
      }

      //Render an Header of type HeaderItem
      renderItem<HeaderItem> {
          //layout res
          res(R.layout.view_holder_header)

          //bind data 
          onBind {
              tv_header_content.text = data.toString()
          }
      }

      //Render an Footer of type FooterItem
      renderItem<FooterItem> {

          //layout res
          res(R.layout.view_holder_footer)

          //bind data 
          onBind {
              tv_footer_content.text = data.toString()
          }
      }
  }

As you can see, it's very simple and intuitive, and you don't see any Adapter or ViewHolder. Equipped with Yasha, go to Gank!

Double Kill

Rendering is done. Where does the data source come from? Yasha thoughtfully prepared a good partner for you:Sange

Sange is another powerful weapon. It can provide any data that Yasha needs. With it, Yasha can be like a fish. As in Dota, they are also inseparable. Friends who are familiar with Dota know that Yasha + Sange = Dark Night The sword is the same here. With both of them, why fear any headwinds?

//Create a DataSource
class DemoDataSource : YashaDataSource() {
   
    //loadInitial is responsible for loading list initialization data
    override fun loadInitial(loadCallback: LoadCallback<YashaItem>) {
        
        //Simulate the delay, don't worry, this method will be executed in an asynchronous thread, so you can rest assured to make network requests or database loading, etc.
        Thread.sleep(1500)

        val allDataList = mutableListOf<YashaItem>()

        //Add Headers data
        for (i in 0 until 2) {
            allDataList.add(HeaderItem(i))
        }
        //Add Items data
        for (i in 0 until 10) {
            allDataList.add(NormalItem(i))
        }
        //Add Footers data
        for (i in 0 until 2) {
            allDataList.add(FooterItem(i))
        }

        //Notify data loading is complete
        loadCallback.setResult(allDataList)
    }

    //loadAfter is responsible for loading the next page of data. Yasha will decide whether to trigger pagination loading by itself. You only need to do the logic to load the next page. Leave the rest to Yasha
    override fun loadAfter(loadCallback: LoadCallback<YashaItem>) {
       
        //when loading failed:
        if (page % 3 == 0) {

            //When data loading fails, you only need to simply tell Yasha a NULL value, and Yasha will automatically stop loading and display a status of loading failure.
            loadCallback.setResult(null)
            return
        }

        //when loading finished:
        if(page == 5) {
            //After the data is loaded, you only need to tell Yasha an empty list, and Yasha will automatically stop loading and display a loading status.            loadCallback.setResult(emptyList())
            return
        }

        //Load the next page of data:
        val items = mutableListOf<YashaItem>()
        for (i in page * 10 until (page + 1) * 10) {
            items.add(NormalItem(i))
        }

        loadCallback.setResult(items)
    }
}

Is it easy? That's right, the API provided by Yasha and Sange is simple and easy to understand. It can be quickly used without any threshold. It is an essential weapon for traveling at home and killing more goods!

In addition, Sange also provides many APIs for directly operating data sources, such as

//Headers
fun addHeader(t: T, position: Int = -1, delay: Boolean = false)
fun addHeaders(list: List<T>, 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<T>, 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)

//Items
fun addItem(t: T, position: Int = -1, delay: Boolean = false)
fun addItems(list: List<T>, position: Int = -1, delay: Boolean = false) 
fun removeItem(t: T, delay: Boolean = false) 
fun setItem(old: T, new: T, delay: Boolean = false)
fun getItem(position: Int): T
fun clearItem(delay: Boolean = false)

//...

Triple Kill

In addition, Yasha also prepared the status display for the younger friends, such as commonly used ** Loading **, ** Loading failed **, ** Loading completed **

If there is any dissatisfaction with the state that comes with it, it is very simple. The first method is to kill it. The second method is to replace it.

//kill it:
class DemoDataSource : YashaDataSource() {

    override fun onStateChanged(newState: Int) {
        //super.onStateChanged(newState)
        //You just need to redo this method and comment out the call to super, so there is no status display!
    }
}

//replace it:
recycler_view.linear(dataSource) {

    //Replace with your own state rendering
    renderItem<YashaStateItem> {
        //new state layout res
        res(R.layout.your_state_view)

        //new state bind
        onBind {
            
        }
        gridSpanSize(spanCount)
        staggerFullSpan(true)
    }
}

Radiant wins, GG

License

Copyright 2019 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.
You might also like...
Modern Calendar View Supporting Both Hijri and Gregorian Calendars but in highly dynamic way
Modern Calendar View Supporting Both Hijri and Gregorian Calendars but in highly dynamic way

KCalendar-View Modern calendar view supporting both Hijri and Gregorian calendar

Clickstream - A Modern, Fast, and Lightweight Android Library Ingestion Platform.
Clickstream - A Modern, Fast, and Lightweight Android Library Ingestion Platform.

Clickstream is an event agnostic, real-time data ingestion platform. Clickstream allows apps to maintain a long-running connection to send data in real-time.

CryptoMovies is a small app that show modern Android developement: with Hilt, Coroutines, Flow, Jetpack and Material Design 3
CryptoMovies is a small app that show modern Android developement: with Hilt, Coroutines, Flow, Jetpack and Material Design 3

CryptoMovies is a small app that show modern Android developement: with Hilt, Coroutines, Flow, Jetpack and Material Design 3.

This app features -  Modern Design, MVVM, Hilt, Room, StateFlow, Jetpack Compose
This app features - Modern Design, MVVM, Hilt, Room, StateFlow, Jetpack Compose

MyMusic is a beautiful app showing how to build modern looking interfaces using Jetpack Compose, recommended libraries, best practices and architectur

A highly customizable calendar library for Android, powered by RecyclerView.
A highly customizable calendar library for Android, powered by RecyclerView.

CalendarView A highly customizable calendar library for Android, powered by RecyclerView. With this library, your calendar will look however you want

RecyclerView Adapter Library with different models and different layouts as convenient as possible.
RecyclerView Adapter Library with different models and different layouts as convenient as possible.

RecyclerView Presenter Convenience library to handle different view types with different presenters in a single RecyclerView. How to install repositor

A simple and easy adapter for RecyclerView. You don't have to make adapters and view holders anymore. Slush will help you.
A simple and easy adapter for RecyclerView. You don't have to make adapters and view holders anymore. Slush will help you.

한국어 No more boilerplate adapters and view holders. Slush will make using RecyclerView easy and fast. The goal of this project is to make RecyclerView,

Android RecyclerView Adapter with nested items & expand/contract functionality
Android RecyclerView Adapter with nested items & expand/contract functionality

AccordionRecycler Android RecyclerView Adapter with nested items & expand/contract functionality With AccordionRecycler you can easily create awesome

💡🚀⭐️ A generalized adapter for RecyclerView on Android which makes it easy to add heterogeneous items to a list
💡🚀⭐️ A generalized adapter for RecyclerView on Android which makes it easy to add heterogeneous items to a list

Mystique is a Kotlin library for Android’s RecyclerView which allows you to create homogeneous and heterogeneous lists effortlessly using an universal

Comments
  • 关于使用自定义RecyclerView的问题

    关于使用自定义RecyclerView的问题

    使用自定义的RecyclerView时,会出现RecyclerView: No adapter attached; skipping layout的问题 自定义类如下

    class JustLoadMoreRecyclerView : RecyclerView {
        private var lastScrollPositions: IntArray? = null      //瀑布流位置存储
        private var loadMore = false
        private var totalPage = 1
        private var currentPage = 1
    
        /**
         * 加载更多
         */
        var onLoadMore: ((page: Int) -> Unit)? = null
    
        constructor(context: Context?) : this(context, null)
        constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
        constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) {
            addOnScrollListener(processMoreListener)
        }
    
        private var processMoreListener: RecyclerView.OnScrollListener = object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
    
                if (adapter == null
                        || recyclerView?.layoutManager == null)
                    return
    
                val totalCount = adapter.itemCount
    
                if (newState == RecyclerView.SCROLL_STATE_IDLE
                        && !loadMore
                        && getLastVisibleItemPosition(recyclerView.layoutManager) + LOAD_MORE_ITEM_SLOP > totalCount) {
                    if (totalPage > currentPage) {
                        loadMore = true
    
                        onLoadMore?.invoke(++currentPage)
                    } else {
                        loadMore = false
                    }
                }
            }
        }
    
        private fun getLastVisibleItemPosition(layoutManager: RecyclerView.LayoutManager): Int {
            return when (layoutManager) {
                is LinearLayoutManager -> layoutManager.findLastVisibleItemPosition()
                is GridLayoutManager -> layoutManager.findLastVisibleItemPosition()
                is StaggeredGridLayoutManager -> {
                    if (lastScrollPositions == null)
                        lastScrollPositions = IntArray(layoutManager.spanCount)
    
                    layoutManager.findLastVisibleItemPositions(lastScrollPositions)
                    max(lastScrollPositions?.max() ?: 0, Int.MAX_VALUE)
                }
                else -> -1
            }
        }
    
        fun setUpPage(currentPage: Int, totalPage: Int) {
            this.currentPage = currentPage
            this.totalPage = totalPage
        }
    
        companion object {
            const val LOAD_MORE_ITEM_SLOP = 2
        }
    }
    
    opened by TakanashiHitomi 3
  • Sticky headers [Feature Request]

    Sticky headers [Feature Request]

    Great library! I love it reduces quiet a lot the boilerplate needed. The only thing thats missing is the possibility to add sticky headers (sections). Any suggestions on how it could be implemented?

    thanks

    opened by majid701 1
  • 为何我clear填的false 但是数据被清空了

    为何我clear填的false 但是数据被清空了

    rcCount.linear { renderItemsByDsl(data.data, false) { item -> xml(R.layout.recycl_item_count_detils) render { it.tvCountContent.text = item.desc it.tvCountMoney.text = item.amount it.tvCountTime.text = item.createTime } } LogUtil.e("${this.adapter.itemCount}") }

    opened by giantbing 0
Owner
Season
会写点代码
Season
Carousel Recyclerview let's you create carousel layout with the power of recyclerview by creating custom layout manager.

Carousel Recyclerview Create carousel effect in recyclerview with the CarouselRecyclerview in a simple way. Including in your project Gradle Add below

Jack and phantom 514 Jan 8, 2023
Delish, a Food Recipes App in Jetpack Compose and Hilt based on modern Android tech-stacks and MVVM clean architecture.

Delish Screens Tech stack & Open-source libraries 100% Kotlin based + Coroutines + Flow for asynchronous. Dagger Hilt 2.37 Accompanist JetPack Jetpack

Mohamed Elbehiry 305 Dec 12, 2022
🪐 Modern Android development with Hilt, Coroutines, Flow, JetPack(ViewModel) based on MVVM architecture.

Ceres ?? Modern Android development with Hilt, Coroutines, Flow, JetPack(ViewModel) based on MVVM architecture. Download Gradle Add the dependency bel

Teodor G. 21 Jan 11, 2023
📒 NotyKT is a complete 💎Kotlin-stack (Backend + Android) 📱 application built to demonstrate the use of Modern development tools with best practices implementation🦸.

NotyKT ??️ NotyKT is the complete Kotlin-stack note taking ??️ application ?? built to demonstrate a use of Kotlin programming language in server-side

Shreyas Patil 1.4k Jan 4, 2023
Android Clean Architecture in Rorty is a sample project that presents modern, approach to Android application development using Kotlin and latest tech-stack.

Android Clean Architecture in Rorty is a sample project that presents modern, approach to Android application development using Kotlin and latest tech-stack.

Mr.Sanchez 176 Jan 4, 2023
Kotlin Dsl for Android RecyclerView

KRecyclerDsl Kotlin Dsl for Android RecyclerView Exemple Sample project recyclerView.adapter = dataClassAdapter<MyView, MyDataClass>(R.layout.my_view,

Thomas Girard 14 Mar 31, 2019
:closed_umbrella: An easy way to implement modern permission instructions popup.

Needs An easy way to implement modern permission instructions popup. Needs can be fully customized and showing with animations. Download Gradle Add be

Jaewoong Eum 609 Dec 8, 2022
Wrapper of FusedLocationProviderClient for Android to support modern usage like LiveData and Flow

FancyLocationProvider Wrapper of FusedLocationProviderClient for Android to support modern usage like LiveData or Flow. Install Add Jitpack repository

Jintin 66 Aug 15, 2022
CleanArchitecture is a sample project that presents a modern, 2021 approach to Android application development.

CleanArchitecture is a sample project that presents a modern, 2021 approach to Android application development. The goal of the pro

Shushant tiwari 0 Nov 13, 2021
Crunch-Mobile - A Food Delivery Mobile App which uses Modern App Architecture Pattern, Firebase And a Simple Restful Api

Crunch-Mobile This is a Food Delivery Mobile App which uses Modern App Architect

Bright Ugwu 1 Jan 1, 2022