...

/

Displaying Data From Code

Displaying Data From Code

Learn and practice how to implement the recycler view adapter to render a list of blog article in this lesson.

Loading data from the Internet

During the previous lessons, we created a BlogHttpClient that loads a list of blog articles. Let’s modify our code to support the new JSON format.

Old JSON format:

Press + to interact
{
"data": [
{
"title": "G'day from Sydney",
"date": "August 2, 2019",
"views": 2687,
"rating": 4.4,
"image": "https://bitbucket.org/dmytrodanylyk/travel-blog-resources/raw/3436e16367c8ec2312a0644bebd2694d484eb047/images/sydney_image.jpg",
"author": {
"name": "Grayson Wells",
"avatar": "https://bitbucket.org/dmytrodanylyk/travel-blog-resources/raw/3436e16367c8ec2312a0644bebd2694d484eb047/avatars/avatar1.jpg"
},
"description": "G'day mate! Welcome to Sydney, where you come for the ..."
}
}

The main changes in the new JSON format are:

  • We have an id attribute
  • The image and avatar now contain a relative path
Press + to interact
{
"data": [
{
"id": 1,
"title": "G'day from Sydney",
"date": "August 2, 2019",
"views": 2687,
"rating": 4.4,
"image": "/images/sydney_image.jpg",
"author": {
"name": "Grayson Wells",
"avatar": "/avatars/avatar1.jpg"
},
"description": "G'day mate! Welcome to Sydney, where you come for the ..."
}
]
}

In the BlogHttpClient, we need to change the URL to the following:

Press + to interact
object BlogHttpClient {
const val BASE_URL = "https://bitbucket.org/dmytrodanylyk/travel-blog-resources"
const val PATH = "/raw/3eede691af3e8ff795bf6d31effb873d484877be"
private const val BLOG_ARTICLES_URL = "$BASE_URL$PATH/blog_articles.json"
...
}

This gives us the ability to concatenate the BASE_URL with the relative path of the blog image or the author avatar. Let’s add additional get methods to the Author class and the Blog class which are going to return full image URLs.

Press + to interact
data class Author(val name: String, val avatar: String) {
fun getAvatarUrl() = BlogHttpClient.BASE_URL + BlogHttpClient.PATH + avatar
}
Press + to interact
data class Blog(
val id: String,
var author: Author,
val title: String,
val date: String,
val image: String,
val description: String,
val views: Int,
val rating: Float
) {
fun getImageUrl() = BlogHttpClient.BASE_URL + BlogHttpClient.PATH + image
}

Now, we can modify the MainActivity code and add a blog loading code similar to what we have in BlogDetailsActivity.

Press + to interact
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
loadData()
}
private fun loadData() {
BlogHttpClient.loadBlogArticles(
onSuccess = { blogList: List<Blog> ->
runOnUiThread { // TODO show data }
},
onError = {
runOnUiThread { showErrorSnackbar() }
}
)
}
private fun showErrorSnackbar() {
Snackbar.make(binding.rootView,
"Error during loading blog articles", Snackbar.LENGTH_INDEFINITE).run {
setActionTextColor(resources.getColor(R.color.orange500))
setAction("Retry") {
loadData()
dismiss()
}
}.show()
}
}

List Adapter

In order for RecyclerView to render and reuse the list of items, we need to use one of the implementations of the ...