dev-resources.site
for different kinds of informations.
Scrolling... Scrolling... RecyclerView for Android with Kotlin!
We all love scrolling (some weird people swipe ĀÆ_(ć)_/ĀÆ).
Scrolling is a major interaction performed almost in every application around.
Letās have a look whatās under the hood of Android implementation of āefficient scrollingā called RecyclerView!
Part One: What is Recycler View and what does it actually recycle? ā»ļø
RecyclerView initiates an efficient way of creating ViewHolder objects, binding them with data and reusing according to a list state.
Imagine, you received 44442
emails on your mobile application (Must be very popular!).
Theoretically, we would think that for every single email there should be a ācell viewā created with email details such as title and short description. But we haveā¦ a lot of emailsā¦ What to do?
RecyclerView comes to help! But how?
It consists from three main elements: cell layout, Adapter and ViewHolder objects.
Cell layout represents an XML design blueprint of a list item. Something like this:
As a next step, Adapter uses a data from the email server, and ābindsā XML view to a particular data such as title or delivery time.
And to perform this binding, Adapter manages something which is called ViewHolder - a class which belongs to RecyclerView, responsible for displaying an item in a view.
And here comes amazing part:
Instead of creating 44442 views for each of our emails, RecyclerView reuses already created view holders which left an observable area of the screen.
What?
Imagine, your list of emails occupies full screen height and can contain 10 emails to be showed.
You start scrolling up.
ā¬ļø
Once the top view is out of view, it is being reused by RecyclerView, with new data and pushed as a new bottom element. Something like that.
Enough of theory, letās do practical part! šØ
Part Two: Letās create a RecyclerView withā¦ Kotlin! ā»ļø
Kotlin is love, Kotlin is life (me ā).
From my point of view, Kotlin is one of the best things which happened to Android :)
It is super easy to write, has a functional approach, easy to understand and hides a lot of boilerplate logic.
What are we waiting for? Letās create our āemailā app project!
NOTE
: All ready copy-paste code is available here
A simple EmptyActivity will be fine for our use case:
Next, letās create our item/cell layout!
For a simple preview, we can use a title, description and a time.
Letās create one in res/layout folder named email_item_layout.xml:
Closer look:
<?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="60dp"
android:background="#FFECECEC"
android:orientation="horizontal"
android:weightSum="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="0.2"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/email_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Let's go to Sydney Vivid tonight!"
android:textColor="@color/colorPrimaryDark"
android:textStyle="bold" />
<TextView
android:id="@+id/email_description"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hey, Nick! There is amazing show near..." />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:orientation="horizontal">
<TextView
android:id="@+id/email_time"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="10:38" />
</LinearLayout>
</LinearLayout>
Alright, whatās next? Ah, unfortunately RecyclerView doesnāt come by default, so we need to import it as external dependency in our build gradle file:
implementation 'com.android.support:recyclerview-v7:28.0.0'
Once it is done, we can create our email data class! We can create āmodelsā package and declare a simple Email class which would contain title, description and delivery time as String attributes:
data class Email(val title: String, val description: String, val time: String)
Done!
Now one of the most interesting parts: The Mighty Adapter!
Letās create a file named EmailAdapter in new package called āadaptersā.
Our EmailAdapter would accept a list of Email objects, context as well as contain a custom ViewHolder:
class EmailAdapter(private val emailList: List<Email>, private val context: Context) : RecyclerView.Adapter<EmailAdapter.EmailViewHolder>() {
override fun onBindViewHolder(emailViewHolder: EmailViewHolder, index: Int) {
emailViewHolder.titleTextView.text = emailList[index].title
emailViewHolder.descriptionTextView.text = emailList[index].description
emailViewHolder.timeTextView.text = emailList[index].time
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EmailViewHolder {
return EmailViewHolder(LayoutInflater.from(context).inflate(R.layout.email_item_layout, parent, false))
}
override fun getItemCount(): Int {
return emailList.size
}
inner class EmailViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val titleTextView: TextView = view.findViewById(R.id.email_title)
val descriptionTextView: TextView = view.findViewById(R.id.email_description)
val timeTextView: TextView = view.findViewById(R.id.email_time)
}
}
onCreateViewHolder
is responsible for inflating XML layout of our email item into an EmailViewHolder
object.
EmailViewHolder
class extends ViewHolder
and references views such as title, description and time TextViews
we declared inside our XML layout, to be used for a data injection inside onBindViewHolder
function.
We are almost done!!!
Now we need to place our RecyclerView XML declaration into activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/email_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
Next step will be to initiate RecyclerView inside MainActivity, and feed some random almost-real email data objects :)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val fakeEmails = generateFakeEmails()
setUpEmailRecyclerView(fakeEmails)
}
private fun setUpEmailRecyclerView(emails: List<Email>) {
val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
val emailRecyclerView = findViewById<RecyclerView>(R.id.email_recycler_view)
val recyclerAdapter = EmailAdapter(emails, this)
emailRecyclerView.layoutManager = layoutManager
emailRecyclerView.adapter = recyclerAdapter
}
private fun generateFakeEmails(): List<Email> {
val titles = listOf(
"Hot dogs $1 only!",
"Dev.to beats Medium.",
"We have updated our privacy :/",
"Nick moves to New Zealand")
val descriptions = listOf(
"This is truly amazing, unexpected...",
"Yes, yes, yes! It is happening!",
"Follow our blog to learn more...",
"Well, it supposed to happen...")
val times = listOf(
"13:42",
"16:16",
"12:34",
"20:20")
val emailList = mutableListOf<Email>()
for (i in 0..10) {
emailList.add(
Email(titles.random(), descriptions.random(), times.random())
)
}
return emailList
}
}
OMG! Look what weāve got!!!
And now we can Recycle our emails š
ļ¼ ^^ļ¼očŖčŖoļ¼^^ ļ¼
Featured ones: