简体   繁体   中英

Recycler view data not loading on screen

I'm trying to show the recycler view's data on my app. The thing is, even though the NetworkStatus is successful (I can tell because I don't get the toast's message and the loader disappears and I can also see the data in the logcat), the info is not displayed. I am not sure if the error is in the way I'm calling the recycler view on my MainActivity or in the RecyclerAdapter but any idea as to where the problem is would be very helpful.

This is the RecyclerAdapter:

import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.app.mortyapp.databinding.ItemDetailBinding

class RecyclerAdapter(private var characterList: List<Character>): RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding = ItemDetailBinding.inflate(
            layoutInflater,
            parent,
            false
        )
        return ViewHolder(binding)
    }

    override fun getItemCount(): Int = characterList.size

    override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
        holder.bind(characterList[position])
    }

    fun setCharacterList(characterList: List<Character>){
        this.characterList = characterList
        notifyDataSetChanged()
    }

    inner class ViewHolder(
        private val binding: ItemDetailBinding
    ) : RecyclerView.ViewHolder(binding.root){
        fun bind(character: Character) {
            with(binding){
                val itemName: TextView = binding.tvName
                val itemGender: TextView = binding.tvGender

                itemName.text = character.name
                itemGender.text = character.gender
            }
        }
    }
}

This is the MainActivity:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.ProgressBar
import android.widget.Toast
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.app.mortyapp.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var  binding: ActivityMainBinding
    private val characters = mutableListOf<Character>()
    private lateinit var progressBar: ProgressBar
    private lateinit var recyclerAdapter: RecyclerAdapter

    private val viewModel: MainViewModel by viewModels(
        factoryProducer = {MainViewModelFactory()}
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        progressBar = binding.ProgressBar
        progressBar.visibility = View.INVISIBLE

        setObservers()
        initRecyclerView()

    }

    private fun initRecyclerView() {
        with(binding.rvCharacters){
            layoutManager = LinearLayoutManager(context)
            recyclerAdapter = RecyclerAdapter(characters).apply {
                setCharacterList(characters)
            }
        }
    }


    private fun setObservers(){
        viewModel.characterList.observe(this, Observer {
            when(it.status){
                NetworkStatus.LOADING ->{
                    //show loading state
                    progressBar.visibility = View.VISIBLE
                }
                NetworkStatus.SUCCESS -> {
                    //hide loading state
                    progressBar.visibility = View.INVISIBLE
                    //render character list
                    recyclerAdapter.setCharacterList(characters)

                }
                NetworkStatus.ERROR -> {
                    //show error message
                    Toast.makeText(this,"Error loading content", Toast.LENGTH_SHORT).show()
                    //hide loading state
                    progressBar.visibility = View.INVISIBLE

                }
            }
        })
    }
}

API response:

import com.google.gson.annotations.SerializedName

data class Character (
    @SerializedName("id") val id: Int,
    @SerializedName("name") val name: String,
    @SerializedName("gender") val gender: String
)

data class CharacterListResponse(
    @SerializedName("results") val results: List<Character>
)

Remote data source:

package com.app.mortyapp

import com.app.mortyapp.Model.CharacterService
import com.app.mortyapp.Model.RetrofitServices
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class CharacterRemoteDataSource {
    fun getCharacterList(networkResponse: NetworkResponse<List<Character>>) {
        val service = RetrofitServices.instance
            .create(CharacterService::class.java)
            .getCharacterList()

        service.enqueue(object : Callback<CharacterListResponse> {
            override fun onResponse(
                call: Call<CharacterListResponse>,
                response: Response<CharacterListResponse>
            ) {
                val resource = response.body()?.run {
                    if (results.isNotEmpty())
                        Resource(NetworkStatus.SUCCESS, results)
                    else
                        Resource(NetworkStatus.ERROR)
                } ?: run {
                    Resource(NetworkStatus.ERROR)
                }
                networkResponse.onResponse(resource)
            }

            override fun onFailure(call: Call<CharacterListResponse>, t: Throwable) {
                networkResponse.onResponse(Resource(NetworkStatus.ERROR, message = t.message))
            }
        })
    }


}

interface NetworkResponse<T> {
    fun onResponse(value: Resource<T>)
}

Set adapter for Recyclerview in

setupRecylerview ()

adapter = recyclerAdapter

NetworkStatus.SUCCESS -> {
                    //hide loading state
                    progressBar.visibility = View.INVISIBLE
                    //render character list
                    recyclerAdapter.setCharacterList(characters)

                    recyclerAdapter.notifydatasetchanged()//add this line 

                }

I think most problems found with recyclerView isn't linked to it, but with some adjourning codes. For example, a very similar problem was solved by finding out that the adapter POJO class was retrieving 0 rather than the actual size of the array list.

See the solved problem here: Android Recycler View not loading Data (Peculiar problem, Not a Duplicate)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM