最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

kotlin - Displaying the items from API in Recycler view in Main Fragment - Stack Overflow

programmeradmin0浏览0评论

I have tried displaying the items from this API

API Link

.php

upon doing logcat all the conditions are true and valid , all the respective adapters are calling but items are not displaying in recyclerview

I have given the intenet permission, and added suitable dependecies of coroutines, retrofit, picasso for displaying the image

What could be the possible issue and how to resolve it, Any help will be much appreciated

This is my HomeFragment file


import retrofit2.HttpException
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.ambrosia.Adaptors.catAdap
import com.example.ambrosia.RetroInstance
import com.example.ambrosia.databinding.FragmentHomeBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.IOException


class HomeFragment : Fragment() {
    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!
    private lateinit var myAdapter: catAdap
    private lateinit var rv :RecyclerView
    private val job = Job()
    private val coroutineScope = CoroutineScope(Dispatchers.Main + job)
    private var isDataLoaded = false // Track if data has been loaded

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        rv = binding.rvCategory
        rv.layoutManager =
            LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
        myAdapter = catAdap(this@HomeFragment, emptyList())
        rv.adapter = myAdapter
        if (!isDataLoaded){
            Log.d("homefragment", "onViewCreated: fetchcategories called sucessfully")
            fetchCategories()
        }
    }

    private fun fetchCategories() {
        coroutineScope.launch {
            val response = try {
                RetroInstance.api.getCategory()
            } catch (e: HttpException) {
                Log.e("HomeFragment", "Http Error: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireContext(), "Network Error", Toast.LENGTH_SHORT).show()
                }
                return@launch
            } catch (e: IOException) {
                Log.e("HomeFragment", "I/O Error: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireContext(), "Network Error", Toast.LENGTH_SHORT).show()
                }
                return@launch
            } catch (e: Exception) {
                Log.e("HomeFragment", "Generic Error: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireContext(), "An Error Occured", Toast.LENGTH_SHORT).show()
                }
                return@launch
            }

            withContext(Dispatchers.Main) {
                if (response.categories.isNotEmpty()) {
                    Log.d("HomeFragment", "Category list size: ${response.categories.size}")
                    myAdapter.catlist = response.categories
                    Log.d("HomeFragment", "after cat;ist called line 2")
                    myAdapter.notifyDataSetChanged()
                    Log.d("HomeFragment", "after notifydtasetchange")
                    myAdapter.onItemClick = { category ->
                        // Handle item click here
                        Log.d("HomeFragment", "Clicked on category: ${category.strCategory}")
                    }
                } else {
                    Log.w("HomeFragment", "Category list is empty")
                    Toast.makeText(requireContext(), "No Categories Found", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }



    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
        job.cancel()
    }
}

This is my Adapter for the recyclerview

package com.example.ambrosia.Adaptors

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import com.example.ambrosia.Models.Category
import com.example.ambrosia.R
import com.squareup.picasso.Picasso


class catAdap(val context: Fragment, var catlist: List<Category>) :
    RecyclerView.Adapter<catAdap.MyViewHolder>(){


    lateinit var onItemClick: ((Category) -> Unit)


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val itemView = LayoutInflater.from(context.requireContext())
            .inflate(R.layout.itemdefine, parent, false) // Inflate your item layout
        return MyViewHolder(itemView)
    }

    override fun getItemCount(): Int {
        return catlist.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem =catlist[position]

        Log.d("TAG", "onBindViewHolder: item displayed succesfully")
        Picasso.get()
            .load(currentItem.strCategoryThumb)
            .into(holder.img)
        Log.d("TAG", "onBindViewHolder: item displayed after picasso")


        holder.itemView.setOnClickListener {
            onItemClick.invoke(currentItem)
        }


    }
    class MyViewHolder (itemView: View) : RecyclerView.ViewHolder(itemView) {
        val img :ImageView
        init {
            img = itemView.findViewById(R.id.rvImg)
        }
    }

}

I have tried displaying the items from this API

API Link

https://www.themealdb/api/json/v1/1/categories.php

upon doing logcat all the conditions are true and valid , all the respective adapters are calling but items are not displaying in recyclerview

I have given the intenet permission, and added suitable dependecies of coroutines, retrofit, picasso for displaying the image

What could be the possible issue and how to resolve it, Any help will be much appreciated

This is my HomeFragment file


import retrofit2.HttpException
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.ambrosia.Adaptors.catAdap
import com.example.ambrosia.RetroInstance
import com.example.ambrosia.databinding.FragmentHomeBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.IOException


class HomeFragment : Fragment() {
    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!
    private lateinit var myAdapter: catAdap
    private lateinit var rv :RecyclerView
    private val job = Job()
    private val coroutineScope = CoroutineScope(Dispatchers.Main + job)
    private var isDataLoaded = false // Track if data has been loaded

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        rv = binding.rvCategory
        rv.layoutManager =
            LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
        myAdapter = catAdap(this@HomeFragment, emptyList())
        rv.adapter = myAdapter
        if (!isDataLoaded){
            Log.d("homefragment", "onViewCreated: fetchcategories called sucessfully")
            fetchCategories()
        }
    }

    private fun fetchCategories() {
        coroutineScope.launch {
            val response = try {
                RetroInstance.api.getCategory()
            } catch (e: HttpException) {
                Log.e("HomeFragment", "Http Error: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireContext(), "Network Error", Toast.LENGTH_SHORT).show()
                }
                return@launch
            } catch (e: IOException) {
                Log.e("HomeFragment", "I/O Error: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireContext(), "Network Error", Toast.LENGTH_SHORT).show()
                }
                return@launch
            } catch (e: Exception) {
                Log.e("HomeFragment", "Generic Error: ${e.message}", e)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireContext(), "An Error Occured", Toast.LENGTH_SHORT).show()
                }
                return@launch
            }

            withContext(Dispatchers.Main) {
                if (response.categories.isNotEmpty()) {
                    Log.d("HomeFragment", "Category list size: ${response.categories.size}")
                    myAdapter.catlist = response.categories
                    Log.d("HomeFragment", "after cat;ist called line 2")
                    myAdapter.notifyDataSetChanged()
                    Log.d("HomeFragment", "after notifydtasetchange")
                    myAdapter.onItemClick = { category ->
                        // Handle item click here
                        Log.d("HomeFragment", "Clicked on category: ${category.strCategory}")
                    }
                } else {
                    Log.w("HomeFragment", "Category list is empty")
                    Toast.makeText(requireContext(), "No Categories Found", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }



    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
        job.cancel()
    }
}

This is my Adapter for the recyclerview

package com.example.ambrosia.Adaptors

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import com.example.ambrosia.Models.Category
import com.example.ambrosia.R
import com.squareup.picasso.Picasso


class catAdap(val context: Fragment, var catlist: List<Category>) :
    RecyclerView.Adapter<catAdap.MyViewHolder>(){


    lateinit var onItemClick: ((Category) -> Unit)


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val itemView = LayoutInflater.from(context.requireContext())
            .inflate(R.layout.itemdefine, parent, false) // Inflate your item layout
        return MyViewHolder(itemView)
    }

    override fun getItemCount(): Int {
        return catlist.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem =catlist[position]

        Log.d("TAG", "onBindViewHolder: item displayed succesfully")
        Picasso.get()
            .load(currentItem.strCategoryThumb)
            .into(holder.img)
        Log.d("TAG", "onBindViewHolder: item displayed after picasso")


        holder.itemView.setOnClickListener {
            onItemClick.invoke(currentItem)
        }


    }
    class MyViewHolder (itemView: View) : RecyclerView.ViewHolder(itemView) {
        val img :ImageView
        init {
            img = itemView.findViewById(R.id.rvImg)
        }
    }

}
Share Improve this question asked Feb 4 at 2:05 Jatin KumarJatin Kumar 111 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

Modify the fetchCategory function in HomeFragment

withContext(Dispatchers.Main) {
    if (response.categories.isNotEmpty()) {
        Log.d("HomeFragment", "Category list size: ${response.categories.size}")
        
        myAdapter.catlist = response.categories
        myAdapter.notifyDataSetChanged() // Notifying the adapter about dataset change
        
        myAdapter.onItemClick = { category ->
            Log.d("HomeFragment", "Clicked on category: ${category.strCategory}")
        }
    } else {
        Log.w("HomeFragment", "Category list is empty")
        Toast.makeText(requireContext(), "No Categories Found", Toast.LENGTH_SHORT).show()
    }
}

Update Constructor parameter's AccessModifier in adapter catAdap

class catAdap(val context: Fragment, private var catlist: List<Category>) :

Add following method in your adapter catAdap

fun updateList(newList: List<Category>) {
    catlist = newList
    notifyDataSetChanged()
}

Now, from fragment, update your list like below:

myAdapter.updateList(response.categories)
发布评论

评论列表(0)

  1. 暂无评论