Android RecyclerView using Kotlin

0
1453
android recyclerview using kotlin

Android Recyclerview is not new to us but Kotlin programming Language is. In fact, we’ve already discussed in our previous article about RecyclerView and CardView Implementation creating a very interesting project “SongBoard” where we’ve created recyclerview and cardview’s implementation and had seen different implementations for Linear, Grid, Staggered Grid and Horizontal implementations of RecyclerView Android.

In this tutorial of Android RecyclerView using Kotlin, we will be focusing on how to create a RecyclerView and declaring RecyclerAdapter using Kotlin Programming language by creating another special project called “News Board”.

NewsBoard is currently being developed by coderefer using the current popular technologies like Data Binding, Kotlin Programming Language, MVVM design Pattern, ViewModel, etc. The link to that project was given at the bottom of this article.

Android RecyclerView and its WhereAbouts:

Although we have discussed about RecyclerView and its whereabouts in our Previous article, in brief, Recyclerview in Android is the advanced version of Listview to efficiently recycle the views and reuse them.

Lets start implementing RecyclerView in our NewsBoard Project.

Implementation of RecyclerView in our Project:

1. Adding required Dependencies:

Firstly, we need to import RecyclerView in order to use it. Here we will also be importing CardView to effectively show the news articles in NewsBoard. To import RecyclerView and CardView, we need to add the following dependencies:

dependencies {
...
//adding a recyclerview
compile "com.android.support:recyclerview-v7:26.1.0"
//adding a cardview
compile "com.android.support:cardview-v7:26.1.0"
...
}

view raw
build.gradle
hosted with ❤ by GitHub

2. Adding RecyclerView to our Layout file:

Now that we have our required dependencies, we will be adding RecyclerView to our Project by adding the following code to our Layout File in which we would like to add the list of News:

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>

view raw
activity_main.xml
hosted with ❤ by GitHub

3. Designing List Item to display each news item:

Now that we’ve added the recyclerview to XML file, let us design a layout for news item, which we would be using to populate our RecyclerView.

Here is the xml code for the News item used in NewsBoard App:

<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.coderefer.newsboard.MainActivity"
>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:cardCornerRadius="4dp"
app:cardElevation="4dp">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_cover"
android:layout_width="match_parent"
android:layout_height="180dp"
android:scaleType="centerCrop"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/img_not_found"/>
<TextView
android:id="@+id/tv_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TechVersus"
app:layout_constraintBottom_toBottomOf="@+id/iv_source"
app:layout_constraintLeft_toRightOf="@+id/iv_source"
app:layout_constraintTop_toTopOf="@+id/iv_source"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="@+id/iv_source"
app:layout_constraintHorizontal_bias="0.66"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/iv_source"
app:srcCompat="@drawable/time"/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="3 days ago"
app:layout_constraintBaseline_toBaselineOf="@+id/tv_source"
app:layout_constraintLeft_toRightOf="@+id/imageView3"/>
<ImageView
android:id="@+id/iv_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="16dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:padding="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_cover"
app:layout_constraintVertical_bias="0.0"
app:srcCompat="@drawable/globe"/>
<TextView
android:id="@+id/tv_heading"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/black_transparent"
android:gravity="start"
android:padding="5dp"
android:text="IPhone 7 Launched in India"
android:textAlignment="textStart"
android:textColor="@android:color/white"
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
app:layout_constraintLeft_toLeftOf="@+id/iv_cover"
app:layout_constraintRight_toRightOf="@+id/iv_cover"/>
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</layout>

view raw
news_item.xml
hosted with ❤ by GitHub

If you’ve Noticed, we are using Android Data Binding in the above xml file, whose implementation is explained in our previous article. We’ll only focus on Android Recycler View implementation for this article.

All the icons used above will be available in the project whose link is given at the bottom of this article.

4. Creating a Model:

Next we would be creating a Model class to model each and every news item that we would be displaying in our NewsBoard.

Here is the simplified form of Model class in Kotlin:

import java.util.Date
data class News(
val id:Int=0,
val news_title:String?=null,
var news_detail: String? = null,
var news_image_url: String? = null,
var news_url: String? = null,
var news_source: String? = null,
var pub_date: Date? = null
)

view raw
News.kt
hosted with ❤ by GitHub

We also used a data class in Kotlin. Data classes helps compiler to automatically derive the functions such as toString(), equals(), hashCode() and copy().

You can also see that we haven’t declared getters and setters.

In Kotlin, getters and setters are optional and are auto-generated if you do not declare them in your program.

5. Adding an Adapter:

Next, we will be adding an adapter class. In brief, adapter class acts as a bridge to bind the data to the recyclerview.

package com.coderefer.newsboard
import android.support.v7.widget.RecyclerView
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.news_item.view.*
/**
* Created by vamsitallapudi on 16/01/18.
*/
class NewsRecyclerAdapter(private val news: ArrayList<News>): RecyclerView.Adapter<NewsRecyclerAdapter.NewsHolder>() {
override fun getItemCount(): Int {
return news.size
}
override fun onBindViewHolder(holder: NewsRecyclerAdapter.NewsHolder, position: Int) {
val itemNews = news[position]
holder.bindNews(itemNews)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsRecyclerAdapter.NewsHolder{
val inflatedView = parent.inflate(R.layout.news_item)
return NewsHolder(inflatedView)
}
class NewsHolder(v:View) : RecyclerView.ViewHolder(v) , View.OnClickListener {
private var view : View = v
private var news : News? = null
init {
v.setOnClickListener {this}
}
override fun onClick(v: View?) {
Log.d("RecyclerView", "CLICK!")
}
fun bindNews(news: News) {
this.news = news
Picasso.with(view.context).load(news.news_image_url).into(view.iv_cover)
view.tv_heading.text = news.news_title
view.tv_source.text = news.news_source
}
}
}

In the above code, at line 25, you might have noticed that i’ve used inflate() on ViewGroup. That is an Extension Function written to extend the existing class and to write our own code. Extension Functions are powerful feature in Kotlin. In fact, Google has just announced Android ktx which provides bunch of extensions useful for Android Development as a library. Here is the code from the file where we would be declaring all the required extension functions for our project.

fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View {
return LayoutInflater.from(context).inflate(layoutRes,this,attachToRoot)
}

view raw
Extensions.kt
hosted with ❤ by GitHub

6. Modifying our Activity / Fragment/s code to show RecyclerView:

The last step is to add the following code to your activity / fragment accordingly to show the data in our recyclerview:

package com.coderefer.newsboard
import android.databinding.DataBindingUtil
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.util.Log
import com.coderefer.newsboard.databinding.ActivityMainBinding
import kotlinx.android.synthetic.main.activity_main.*
import org.json.JSONArray
import org.json.JSONObject
import java.io.InputStream
class MainActivity : AppCompatActivity() {
var mBinding: ActivityMainBinding? = null
private val TAG : String = "MainActivity"
private lateinit var linearLayoutManager:LinearLayoutManager
private lateinit var mAdapter: NewsRecyclerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = DataBindingUtil.setContentView(this,R.layout.activity_main)
linearLayoutManager = LinearLayoutManager(this)
val jsonString:String = readJsonFromKotlinFile()
val newsList : ArrayList<News> = parseJsonStringToNewsList(jsonString)
// can also be declared as kotlin by default supports data binding
// recyclerView.layoutManager = linearLayoutManager
// using android's data binding library here
mBinding?.recyclerView?.layoutManager = linearLayoutManager
mAdapter = NewsRecyclerAdapter(newsList)
recyclerView.adapter = mAdapter
}
private fun parseJsonStringToNewsList(jsonString: String): ArrayList<News> {
val newsList :ArrayList<News> = ArrayList<News>(0)
val newsArray = JSONArray(jsonString)
var i = 0
var numIterations = newsArray.length()
while(i < numIterations){
val newsObject:JSONObject = newsArray.getJSONObject(i)
val news = News()
news.news_title = newsObject.getString("news_title")
news.news_image_url = newsObject.getString("news_image_url")
news.news_source = newsObject.getString("news_source")
news.news_detail = newsObject.getString("news_detail")
news.news_url = newsObject.getString("news_url")
news.id = newsObject.getInt("id")
newsList.add(news)
i++
}
return newsList
}
private fun readJsonFromKotlinFile() :String{
var inputString = ""
try {
val inputStream:InputStream = assets.open("news_data_file.json")
inputString = inputStream.bufferedReader().use{it.readText()}
Log.d(TAG,inputString)
} catch (e:Exception){
Log.d(TAG, e.toString())
}
return inputString
}
}

view raw
MainActivity.kt
hosted with ❤ by GitHub

If you are using fragment, make sure you’ve added your code in onCreateView() method instead.

If you’ve observed the above code, i am reading the json file from local and parsing it to fill the Android RecyclerView. We’ve discussed on how to read a local file using Kotlin in our previous article.

This completes our tutorial on Android RecyclerView using Kotlin where we’ve used Data binding, Extension Functions and filling recyclerview by parsing the data from local json file.

Complete code:

The link for the complete code is given below:

https://github.com/vamsitallapudi/NewsBoard/tree/recyclerview-implementation

0 0 vote
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments