How to show JSON data into RecyclerView using adapter in Kotlin?

I have succeeded pulling JSON from Reddit API but I cannot put it into my RecyclerView. I set a Log to check if my JSON is empty or null, and the Log successfully print the desired output, so that means my JSON is not empty and contains the necessary data.

Here is my HomeFragment.kt

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.d(javaClass.simpleName, "onViewCreated")
        val rv = binding.recyclerView
        val adapter = PostRowAdapter(viewModel)
        rv.adapter = adapter
        rv.layoutManager = LinearLayoutManager(binding.root.context)

        viewModel.netFetchData()
        viewModel.observeData().observe(viewLifecycleOwner) {
            Log.d("asd","show me the author from json first index : "+it.get(0).author)
            adapter.submitList(it)
            adapter.notifyDataSetChanged()
        }
        //adapter.notifyDataSetChanged()
    }

Here is my MainViewModel.kt

    fun netFetchData() = viewModelScope.launch(
        context = viewModelScope.coroutineContext
                + Dispatchers.IO) {
        data.postValue(repository.getPosts(subreddit.value.toString()))
    }

    fun observeData(): LiveData<List<RedditPost>> {
        return data
    }

Here is my PostRowAdapter.kt

class PostRowAdapter(private val viewModel: MainViewModel)
    : ListAdapter<RedditPost, PostRowAdapter.VH>(RedditDiff()) {
    private var awwRow = listOf<RedditPost>()

    class RedditDiff : DiffUtil.ItemCallback<RedditPost>() {
        override fun areItemsTheSame(oldItem: RedditPost, newItem: RedditPost): Boolean {
            return oldItem.key == newItem.key
        }
        override fun areContentsTheSame(oldItem: RedditPost, newItem: RedditPost): Boolean {
            return RedditPost.spannableStringsEqual(oldItem.title, newItem.title) &&
                    RedditPost.spannableStringsEqual(oldItem.selfText, newItem.selfText) &&
                    RedditPost.spannableStringsEqual(oldItem.publicDescription, newItem.publicDescription) &&
                    RedditPost.spannableStringsEqual(oldItem.displayName, newItem.displayName)

        }
    }

    inner class VH(val binding: RowPostBinding)
        : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        val binding = RowPostBinding.inflate(LayoutInflater.from(parent.context),
            parent, false)
        return VH(binding)
    }

    override fun onBindViewHolder(holder: VH, position: Int) {
        val binding = holder.binding
        awwRow[position].let{
            binding.title.text = it.title
            Glide.glideFetch(it.imageURL,it.thumbnailURL,binding.image)
            binding.selfText.text = it.selfText
            binding.score.text = it.score.toString()
            binding.comments.text = it.commentCount.toString()
        }
    }
    override fun getItemCount() = awwRow.size
}

I thought my code was correct, but when I ran the app, the RecyclerView still blank. Where am I wrong?

>Solution :

your PostRowAdapter is populating awwRow list, which is empty on start and never updated, thus this RecyclerView will always contain 0 elements

if you are using ListAdapter and submitList(...) method then you shouldn’t override getItemCount and you shouldn’t have own data list, so remove these lines

private var awwRow = listOf<RedditPost>() // on top

override fun getItemCount() = awwRow.size // on bottom

if you want access to whole list set with submitList() method then you can call inside adapter getCurrentList(). if you need a particular item at position (like in onBindViewHolder) then use getItem(position). So instead of

 awwRow[position].let{

you should have

getItem(position).let{

Leave a Reply