Translation Instructions:

Kotlin & RecyclerView for High Performance Lists in Android

Original address: www.andreasjakl.com

Originally written by Andreas Jakl

RecyclerView is the best way to display scrolling lists on Android. It ensures high performance and smooth scrolling while providing list elements with flexible layouts. Combined with Kotlin’s modern language capabilities, RecyclerView’s code overhead is greatly reduced compared to traditional Java methods.

Example project: PartsList – Getting started

In this article, we’ll look at an example scenario: maintaining a scrolling list of machine parts for an application: “PartsList.” However, this scheme only affects the strings we use – you can copy this method for any use case you need.

To get started, create a new Android application using Android Studio 3+. Make sure Kotlin support is enabled and select the “Empty” template for MainActivity. Or, if you don’t want to code the following steps manually, download the completed source code from GitHub.

What is RecyclerView?

The screen list in Android consists of multiple subviews. Each has a layout of one or more views. For example, an email application shows you multiple emails; Each of these items includes a subject, a sender’s name, and a bunch of other information.

Parsing the XML layout of a subview and extending it to an instance of a class is a performance-consuming operation. Fast swiping can put a lot of strain on a phone’s performance. The goal is to stick to 60 frames per second at all times. However, this leaves less than 17 milliseconds of computation time per frame.

The main trick of RecyclerView is to reuse the subviews in the list. Once the subview rolls out of the visible area, it is basically put in a queue. Sooner or later, it will be used again when the new subview scrolls. The UI text content of the subview is then replaced. The RecyclerView principle is shown below:

RecyclerView process

Unfortunately, this effective approach requires some architectural background. It may seem strange at first. However, once you have all the components, you can easily customize them.

RecyclerView requires configuration/implementation of the following components:

  • RecyclerView: Manage everything. It is primarily pre-written by Android. You provide components and configurations.
  • Adapter: You will spend most of your time writing this class. It connects to the data source. Under RecyclerView instructions, it creates or updates each item in the list.
  • ViewHolder: A simple class that allocates/updates data in view items. When the view is reused, the previous data is overwritten.
  • Data Source: Anything you like – from simple arrays to complete Data sources. Your adapter interacts with it.
  • LayoutManager: Is responsible for putting all individual view items on the screen and making sure they get the screen space they need.

Data source and Kotlin data classes

Our data source is a simple list/array. The list consists of instances of custom classes. You can hardcode these in your application, or you can create them on the fly – for example, based on HTTP REST requests from online sources.

Kotlin has a nice feature that simplifies writing data classes. This method works for all classes that contain only data but no operations. Our sample data class is called PartData because it stores information about the computer parts that maintain the application.

data class PartData ( val id: Long, val itemName: String)
Copy the code

For data classes, Kotlin automatically generates all utility functions:

  • Properties: You no longer need to write as normal Javagettersetter.
  • Additional features: for example,equals().hasCode().toString()copy().

Antonio Leiva has written a great article comparing Java with Kotlin in the same data class context. You can save about 80% of the code and still get the same results.

You instantiate the Kotlin data class just like any other class. Note that Kotlin does not use the new statement, so we just use the class name and supply the value to the constructor argument. Add the code to nCreate() in your MainActivity.


var partList = ArrayList<PartData>()
partList.add(PartData(100411, "LED Green 568 nm, 5mm"))
partList.add(PartData(101119, "Aluminium Capacitor 4.7 u F"))
partList.add(PartData(101624, "500 k Ω Potentiometer"))
// ...

Copy the code

List item Layout

Every project in RecyclerView requires a custom layout. You can create this file in any of the same ways as the Activity layout: in the Android-style project view of Android Studio, open App > RES > Layout. Right-click on the “Layout” folder name and choose New > Layout Resource File. Create a layout named part_list_item.xml.

For example use cases, use the following properties:

  • Layout: LinearLayout(vertical)
  • Width: match_parent
  • Height: wrap_content
  • Padding: 16dp

Next, add two child items to the layout. We’re going to use TextView. Just make sure you give them useful ids, because we need these to assign the text in Kotlin code:

  • Id 1: @+id/tv_part_item_name (larger text size)
  • Id 2: @+id/tv_part_id (smaller text size)

Recycler View Dependencies

Add RecyclerView to the Android system using Android 5.0 (API level 21). Many applications are still targeted at Android 4.4+, so you typically use RecyclerView through the AppCompat/Support library. Include the latest version of the support libraries (depending on your build SDK) in the.gradle file as a dependency of your application build.

implementation 'com. Android. Support: appcompat - v7:26.1.0'
implementation 'com. Android. Support: recyclerview - v7:26.1.0'
Copy the code

After we add this definition, we can start writing the source code to use RecyclerView.

ViewHolder: Processes a single item in the list

First, create a class called PartAdapter. Put it in the same directory as MainActivity. Within this class, create a nested class named PartViewHolder.

class PartViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    fun bind(part: PartData) {
        itemView.tv_part_item_name.text = part.itemName
        itemView.tv_part_id.text = part.id.toString()
    }
}
Copy the code

This ViewHolder introduces the project view. In addition, it stores metadata about its location in RecyclerView.

Essentially, the main task of our ViewHolder implementation is to bind the currently needed data to a previously bloated UI layout. Whenever a new item is visible during scrolling, this class ensures that the view of the item shows what we expect to be at that point in the list.

To update the UI, we create our own method and call it bind(). Note that this is not an overriding method of the base class, so we can give it any name we want. As method parameters, we just need to display the data in the UI. In bind(), we simply assign the supplied data to the view item.

(Technically, we don’t bind it, we just allocate data. If the data model changes, it will not automatically update the visible list in this implementation.

Kotlin: Main constructor

If you’re new to Kotlin, you might be wondering: How do we access itemView in bind()? Where does it come from?

The magic is called the main constructor. In Kotlin, it can be part of the class title. The previous constructor keyword is optional.

class PartViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { ... }
Copy the code

What good is that? Kotlin automatically provides all parameters as attributes. Therefore, we do not see property definitions and initializations. Instead, we simply access the property from bind().

RecyclerView Adapter: Pin it together

We are exploring the most important component of the RecyclerView architecture: the adapter. It has three main tasks:

Let’s take a look at the adapter in the larger picture and where these three tasks fit:

  1. To draw a list on the screen, RecyclerView asks how many items the adapter has in total. Our adapter returns this information in getItemCount().
  2. Whenever RecyclerView decides that it needs another view instance in memory, it calls onCreateViewHolder(). In this approach, the adapter expands and returns the XML layout we created in the previous step.
  3. The RecyclerView instructs the adapter to update its data each time a ViewHolder previously created is used (re). We customize this procedure by overriding onBindViewHolder().

You don’t have to write code to override these three functions manually. Simply extend the definition of the PartAdapter class. Make it inherit the RecyclerView adapter. Android Studio will automatically prompt you to implement all the necessary members:

Then, add the parameter “partItemList” to the PartAdapter class. Use the primary constructor. This will allow MainActivity to provide the data model when instantiating the PartAdapter.

As before, the partItemList parameter is automatically used as an attribute. In our case, the property type is a simple list (array) of our data classes.

class PartAdapter (val partItemList: List<PartData>, val clickListener: (PartData) -> Unit) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() {
Copy the code

RecyclerView adapter implementation

Android Studio has created method stubs. We only need to write a few lines of implementation. This code customizes the adapter to our requirements and accomplishes the three main tasks I have described.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    // LayoutInflater: takes ID from layout defined inXML. // Instantiates the layout XML into corresponding View objects. // Use context from main app -> also supplies theme  layout values! val inflater = LayoutInflater.from(parent.context) // Inflate XML. Last parameter: don't immediately attach new view to the parent view group val view = inflater.inflate(R.layout.part_list_item, parent, false) return PartViewHolder(view) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { // Populate ViewHolder with data that corresponds to the position in the list // which we are told to load (holder as PartViewHolder).bind(partItemList[position]) } override fun getItemCount() = partItemList.sizeCopy the code
  • OnCreateViewHolder () : Extends the layout XML of the view item.inflate()The last parameter to the method ensures that the new view is not immediately attached to the superview group. Instead, it is only in the cache and should not be visible.
  • OnBindViewHolder () : Provides all the necessary information in RecyclerView – the data that should be displayed in the ViewHolder instance, as well as the (new) location in the data list. Using our Adapter classpartItemListProperty that we call the custom we added to the ViewHolderbind()Function.
  • GetItemCount () : simple in our example – list/array size. In Kotlin, we can further simplify this to an inline implementation; If we return a value directly/a simple expression, we do not need the {} and return statements of functions.

RecyclerViews activity layout

We’re almost done. Next, we create RecyclerView. The first step is to add it to the MainActivity’s XML layout definition.

If you use Android Studio’s new project wizard and create an empty activity, a “Hello World” TextView is added. Delete it.

Instead, add the following definition to the scrolling full-screen RecyclerView list with ID “rv_parts” :

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_parts"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Copy the code

Instantiation RecyclerView

Only three lines of code are needed in MainActivity’s onCreate().

  1. Assign LayoutManager: It measures and locates the project view. Different layout managers support various layouts. We chose the most common: LinearLayoutManager. By default, it creates a vertical scrolling list layout.
rv_parts.layoutManager = LinearLayoutManager(this)
Copy the code
  1. Optimization: The size of RecyclerView is not affected by the adapter content. The size of RecyclerView depends only on the parent (in our example, full screen is available). Therefore, we can call setHasFixedSize() to activate some optimizations in RecyclerView. In Kotlin, you don’t need “set” -prefix to access properties.
rv_parts.hasFixedSize()
Copy the code
  1. Allocate adapters: This ultimately connects everything: we create and assign a new instance of the Adapter class we wrote (” PartAdapter “). The list of data items required by the adapter is the one we created at the beginning of this article.
rv_parts.adapter = PartAdapter(testData)
Copy the code

RecyclerView: Work!

Now press Play and your RecyclerView should work normally! Using the three sample data items we provide, the list is a little too short to fully understand scrolling. To test it, just expand the list with some additional projects.

Now that you have the basics, you can easily extend the project layout and data classes, as well as other information.

If something doesn’t work for you, compare your code to the completion solution on GitHub. Note that the solution is more advanced than we were at this stage – for example, it already includes a click handler.

Next step: Click Handler

One frequently used part is missing: the click handler. These are much more complex in RecyclerViews than in ListView. However, if done well, they can easily add Kotlin. It’s just a matter of understanding some of the more advanced Kotlin concepts. We’ll look at this in the next section!

Welcome to Kotlin Chinese community!

Chinese official website:www.kotlincn.net/

Chinese official Blog:www.kotliner.cn/

Public id: Kotlin

Zhihu Column:Kotlin

CSDN:Kotlin Chinese Community

The nuggets:Kotlin Chinese Community

Jane:Kotlin Chinese Community