My App is just shows an Empty Screen and RecyclerView is not showing anything or is not working but there are no compile time or run time errors.
It would be great help if I get an answer ...
I have been making an app that uses a RecyclerView but it's not showing any thing..why contents of the recycler view have not been showing up.my codes are bellow
Here is My FeedFragment, Adapter
//Fragment
#AndroidEntryPoint
class FeedFragment : Fragment(R.layout.feed_fragment) {
private var _binding: FeedFragmentBinding? = null
private val binding get() = _binding!!
private lateinit var feedAdapter: FeedAdapter
private val viewModel: FeedViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FeedFragmentBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRv()
getCharacters()
}
private fun getCharacters() {
viewModel.listData.observe(viewLifecycleOwner, Observer { pagingData ->
feedAdapter.submitData(viewLifecycleOwner.lifecycle, pagingData)
})
}
private fun setupRv() {
feedAdapter = FeedAdapter()
binding.feedRv.layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
binding.feedRv.apply {
adapter = feedAdapter
setHasFixedSize(true)
visibility = View.VISIBLE
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
//PagingDataAdapter
class FeedAdapter : PagingDataAdapter<Characters,FeedAdapter.FeedViewHolder >(DiffCallback()) {
inner class FeedViewHolder(private val binding: FeedFragmentRvBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(characters: Characters) {
with(binding) {
Glide.with(itemView)
.load(characters.image)
.transition(DrawableTransitionOptions.withCrossFade())
.error(R.drawable.ic_launcher_background)
.into(feedRvImage)
feedRvName.text = characters.name
feedRvStatus.text = characters.status
feedRvSpecies.text = characters.species
feedRvGender.text = characters.gender
println(characters.name)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeedViewHolder {
val binding =
FeedFragmentRvBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return FeedViewHolder(binding)
}
override fun onBindViewHolder(holder: FeedViewHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
class DiffCallback : DiffUtil.ItemCallback<Characters>() {
override fun areItemsTheSame(oldItem: Characters, newItem: Characters): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Characters, newItem: Characters): Boolean {
return oldItem == newItem
}
}
}
// retrofit response
Update your CharacterResponse model class to parse data accordingly.
data class CharacterResponse(
val info: Info,
val results: List<Characters>
)
Related
I have home fragment and I want it to go to another fragment which will show its "details", which passes the data of the clicked recyclerview item to that "details" fragment.
When I click the article it will move to detail article which passes the data.
As for the code, here's the adapter:
class ArticleAdapter(private val articleList: ArrayList<Article>) :
RecyclerView.Adapter<ArticleAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val binding = ItemArticleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyViewHolder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val data = articleList[position]
holder.bind(data)
}
class MyViewHolder(private val binding: ItemArticleBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(data: Article) {
Glide.with(binding.root.context)
.load(data.img)
.into(binding.articleImage)
binding.articleTitle.text = data.title
binding.root.setOnClickListener {
val article = Article(
data.title,
data.img,
data.content
)
}
}
}
override fun getItemCount(): Int {
return articleList.size
}
}
Here's my detailFragment
class DetailArticleFragment : Fragment() {
private var _binding: FragmentDetailArticleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentDetailArticleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val intent = Intent(binding.root.context, DetailArticleFragment::class.java)
val article = intent.getParcelableExtra<Article>(DETAIL_ARTICLE) as Article
Glide.with(this)
.load(article.img)
.into(_binding!!.articleImage)
_binding!!.articleTitle.text = article.title
_binding!!.articleDescription.text = article.content
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
const val DETAIL_ARTICLE = "detail_article"
}
}
You need to pass click listener interface to adapter, for example:
typealias OnArticleClick = (article: Article) -> Unit
class ArticleAdapter(
private val articleList: ArrayList<Article>
) :
RecyclerView.Adapter<ArticleAdapter.MyViewHolder>() {
var onArticleClick: OnArticleClick? = null
...
binding.root.setOnClickListener {
val article = Article(
data.title,
data.img,
data.content
)
onArticleClick?.invoke(article)
}
...
}
And init onArticleClick in your home fragment with RecyclerView:
adapter.apply {
onArticleClick = {
// show details fragment
}
}
I have a RecyclerView in MVVM project. I have to get text from editText (searchWordEt) and then pass it to the function that invokes API method in viewmodel.API works fine and returns data. But when I invoke searchDefAdapter.submitList(response) in SearchFragment nothing happens and RecyclerView data not showing.
class SearchDefAdapter(
private var infoListener: OnItemClickListener,
private var addListener: OnItemClickListener
):
ListAdapter<Def, SearchDefViewHolder>(differCallback) {
interface OnItemClickListener {
fun onItemClick(position: Int)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchDefViewHolder {
return SearchDefViewHolder(
SearchWordCardBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
),
addListener,
infoListener
)
}
override fun onBindViewHolder(holder: SearchDefViewHolder, position: Int) {
holder.bind(getItem(position))
}
}
class SearchDefViewHolder(
private val binding: SearchWordCardBinding,
addListener: SearchDefAdapter.OnItemClickListener,
infoListener: SearchDefAdapter.OnItemClickListener
): RecyclerView.ViewHolder(binding.root) {
fun bind(data: Def) {
with (binding) {
searchCardTv.text = "${data.text} - ${data.tr[0].text}"
}
}
init {
binding.addSearchCard.setOnClickListener {
addListener.onItemClick(adapterPosition)
}
binding.infoSearchCard.setOnClickListener {
infoListener.onItemClick(adapterPosition)
}
}
}
val differCallback = object : DiffUtil.ItemCallback<Def>() {
override fun areItemsTheSame(oldItem: Def, newItem: Def): Boolean {
return oldItem.text == newItem.text
}
override fun areContentsTheSame(oldItem: Def, newItem: Def): Boolean {
return oldItem == newItem
}
}
#AndroidEntryPoint
class SearchFragment : Fragment() {
private var _binding: FragmentSearchBinding? = null
private val binding get() = _binding!!
lateinit var searchDefAdapter: SearchDefAdapter
private val viewModel: DictionaryViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentSearchBinding.inflate(inflater, container, false)
val view = binding.root
searchDefAdapter = SearchDefAdapter(
object : SearchDefAdapter.OnItemClickListener {
override fun onItemClick(position: Int) {
Log.d("tag", "Item Added!")
//viewModel.saveWord(position)
}
},
object : SearchDefAdapter.OnItemClickListener {
override fun onItemClick(position: Int) {
val wordFragment = WordFragment()
fragmentManager?.beginTransaction()?.replace(
R.id.nav_host_fragment_container,
wordFragment
)?.commit()
}
}
)
setUpRecyclerView(searchDefAdapter)
var job: Job? = null
binding.searchWordEt.addTextChangedListener { editable ->
job?.cancel()
job = MainScope().launch {
delay(SEARCH_WORD_TIME_DELAY)
editable?.let {
if (editable.toString().isNotEmpty())
viewModel.getTranslation(editable.toString())
}
}
}
viewModel.def.observe(viewLifecycleOwner, Observer { response ->
binding.apply {
searchDefAdapter.submitList(response)
}
})
return view
}
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
private fun setUpRecyclerView(adapter: SearchDefAdapter){
binding.searchRv.apply {
adapter
layoutManager = LinearLayoutManager(activity)
}
}
}
You haven't actually set the adapter in setUpRecyclerView()
private fun setUpRecyclerView(myAdapter: SearchDefAdapter){
binding.searchRv.apply {
layoutManager = LinearLayoutManager(activity)
adapter = myAdapter // here
}
}
I am following this article here.
All is working well but now I want to implement the onclicklistener for each item.
Here's my code:
SongViewModelAdapter.kt
class SongViewModelAdapter(private val onSelect: ((ViewModelLyric?) -> Unit)?) : PagingDataAdapter<ViewModelLyric,
SongViewModelAdapter.SongViewHolder>(Companion) {
val TAG = "SongViewModelAdapter"
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val dataBinding = LyricDataBinding.inflate(
layoutInflater,
parent,
false
)
return SongViewHolder(dataBinding)
}
override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
val lyric = getItem(position) ?: return
holder.bindLyric(lyric, onSelect)
}
companion object : DiffUtil.ItemCallback<ViewModelLyric>() {
override fun areItemsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
return oldItem == newItem
}
}
inner class SongViewHolder(
private val dataBinding: LyricDataBinding
) : RecyclerView.ViewHolder(dataBinding.root) {
fun bindLyric(lyric: ViewModelLyric, onSelect: ((ViewModelLyric?) -> Unit)?) {
dataBinding.itemTitle.text = lyric.title
dataBinding.itemArtist.text = lyric.artist
dataBinding.root.setOnClickListener {
onSelect?.let { it1 -> it1(lyric) }
}
}
}
}
HomeFragment.kt
#AndroidEntryPoint
class HomeFragment : Fragment() {
val TAG = "HomeFragment"
private lateinit var binding : FragmentHomeBinding
private val viewModel by viewModels<HomeFragmentViewModel>()
private var adapter = SongViewModelAdapter(null)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_home, container, false)
binding.productsRecyclerView.adapter = SongViewModelAdapter(::onSelect)
return binding.root
}
private fun onSelect(viewModelLyric: ViewModelLyric?) {
val id = viewModelLyric?.id
val bundle = bundleOf("id" to id)
Log.d(TAG, id.toString())
view?.findNavController()?.navigate(R.id.songDetailFragment, bundle)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setLyricsAdapter()
getLyrics()
setProgressBarAccordingToLoadState()
}
private fun setLyricsAdapter() {
binding.productsRecyclerView.adapter = adapter
}
private fun getLyrics() {
lifecycleScope.launch {
viewModel.flow.collectLatest {
adapter.submitData(it)
}
}
}
private fun setProgressBarAccordingToLoadState() {
lifecycleScope.launch {
adapter.loadStateFlow.collectLatest {
binding.progressBar.isVisible = it.append is LoadState.Loading
}
}
}
}
I am using FirestorePagingAdapter at the moment and it works well. For those experienced in paging 3, how would you pass total items to implement the click listener for each item. Saw similar questions but never a clear solution. Been scratching my head for a day. Your help will be much appreciated.
Edit 1: Added HomeFragment.kt
Edit 2: Updated with user suggestions. Click still not working. I needed to add the null checks.
It is not a good practice to handle click inside your adapter.
The adapter concern is just to act as a bridge b/w our data and the recyclerview not to handle click. Passing it back to fragment/activity restores that. Second, using callbacks may lead to Memory leaks as it going to have the reference to the fragment/activity.
class YourRecyclerViewAdapter(private val onSelect: (ViewModelLyric?) -> Unit) : PagingDataAdapter<ViewModelLyric, SongViewModelAdapter.SongViewHolder>(Companion) {
override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
val lyric = getItem(position) ?: return
holder.bindLyric(lyric)
}
class SongViewHolder(private val binding: YourViewBinding) : RecyclerView.ViewHolder(dataBinding.root) {
fun bindLyric(yourDataType: ViewModelLyric?, onSelect: (ViewModelLyric?) -> Unit) {
dataBinding.itemTitle.text = lyric.title
dataBinding.itemArtist.text = lyric.artist
dataBinding.root.setOnClickListener {
onSelect(yourDataType)
}
}
}
}
In your Fragment/Activity
// Set this adapter to your recycler view
binding.productsRecyclerView.adapter = YourRecyclerViewAdapter { viewModelLyric->
// Handle click here
}
EDIT:
SongViewModelAdapter
class SongViewModelAdapter(private val onSelect: (ViewModelLyric) -> Unit) : PagingDataAdapter<ViewModelLyric, SongViewModelAdapter.SongViewHolder>(Companion) {
val TAG = "SongViewModelAdapter"
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val dataBinding = LyricDataBinding.inflate(layoutInflater, parent, false)
return SongViewHolder(dataBinding)
}
override fun onBindViewHolder(holder: SongViewHolder, position: Int) {
val lyric = getItem(position) ?: return
holder.bindLyric(lyric, onSelect)
}
companion object : DiffUtil.ItemCallback<ViewModelLyric>() {
override fun areItemsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: ViewModelLyric, newItem: ViewModelLyric): Boolean {
return oldItem == newItem
}
}
class SongViewHolder(private val dataBinding: LyricDataBinding) : RecyclerView.ViewHolder(dataBinding.root) {
fun bindLyric(lyric: ViewModelLyric, onSelect: (ViewModelLyric) -> Unit)) {
dataBinding.itemTitle.text = lyric.title
dataBinding.itemArtist.text = lyric.artist
dataBinding.root.setOnClickListener {
onSelect(lyric)
}
}
}
}
HomeFragment
#AndroidEntryPoint
class HomeFragment : Fragment() {
val TAG = "HomeFragment"
private lateinit var binding : FragmentHomeBinding
private val viewModel by viewModels<HomeFragmentViewModel>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
binding.productsRecyclerView.adapter = SongViewModelAdapter(::onSelect)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getLyrics()
setProgressBarAccordingToLoadState()
}
private fun onSelect(lyric: ViewModelLyric) {
// handle click here
}
private fun getLyrics() {
lifecycleScope.launch {
viewModel.flow.collectLatest {
binding.adapter.submitData(it)
}
}
}
private fun setProgressBarAccordingToLoadState() {
lifecycleScope.launch {
adapter.loadStateFlow.collectLatest {
binding.progressBar.isVisible = it.append is LoadState.Loading
}
}
}
}
I implemented SelectionTracker for RecycleView and it works fine until I navigate to another fragment and press the back button. After navigation, it stops working correctly and after selection I can't deselect item anymore.
I created a sample project on github and I can reproduce bug there:
https://github.com/alborozd/RecycleViewSelectionProblem
Here is my code from that sample project:
Adapter and ViewHolder:
class MyListAdapter()
: ListAdapter<MyModel, MyListAdapter.MyItemViewHolder>(DiffCallback()) {
init {
setHasStableIds(true)
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
private var tracker: SelectionTracker<String>? = null
fun setTracker(tracker: SelectionTracker<String>?) {
this.tracker = tracker
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyItemViewHolder {
return MyItemViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false),
this
)
}
override fun onBindViewHolder(holder: MyItemViewHolder, position: Int) {
val item = getItem(position)
holder.bind(item, tracker!!.isSelected(item.id))
}
class MyItemViewHolder(itemView: View, private val adapter: MyListAdapter) : RecyclerView.ViewHolder(itemView) {
private var text: TextView? = null
private var container: View? = null
init {
text = itemView.findViewById(R.id.text)
container = itemView.findViewById(R.id.itemContainer)
}
fun bind(item: MyModel, selected: Boolean) {
text?.text = item.name
if (selected) {
val theme = itemView.context!!.theme
container?.setBackgroundColor(
itemView.context!!.resources.getColor(
android.R.color.darker_gray,
theme
)
)
} else {
container?.setBackgroundColor(0)
}
}
fun getItemDetails(): ItemDetailsLookup.ItemDetails<String> =
object : ItemDetailsLookup.ItemDetails<String>() {
override fun getPosition(): Int = adapterPosition
override fun getSelectionKey(): String? = adapter.getItem(adapterPosition).id
override fun inSelectionHotspot(e: MotionEvent): Boolean {
return true
}
}
}
class DiffCallback : DiffUtil.ItemCallback<MyModel>() {
override fun areItemsTheSame(oldItem: MyModel, newItem: MyModel): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: MyModel, newItem: MyModel): Boolean {
return oldItem == newItem
}
}
}
ItemIdKeyProvider:
class ItemIdKeyProvider(
private val adapter: MyListAdapter
) : ItemKeyProvider<String>(SCOPE_MAPPED) {
override fun getKey(position: Int): String? {
return adapter.currentList[position].id
}
override fun getPosition(key: String): Int {
return adapter.currentList.indexOfFirst { c -> c.id == key }
}
}
ItemLookup:
class ItemLookup(private val rv: RecyclerView) : ItemDetailsLookup<String>() {
override fun getItemDetails(event: MotionEvent)
: ItemDetails<String>? {
val view = rv.findChildViewUnder(event.x, event.y)
if (view != null) {
return (rv.getChildViewHolder(view) as MyListAdapter.MyItemViewHolder)
.getItemDetails()
}
return null
}
}
And here is how I initialize all of this in my fragment:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
viewModel = createViewModel()
binding = DataBindingUtil.inflate(inflater, R.layout.main_fragment, container, false)
binding.viewModel = viewModel
binding.lifecycleOwner = this
viewModel.initViewModel()
viewModel.items.observe(this, Observer { items ->
val adapter = MyListAdapter()
adapter.submitList(items)
binding.recycleView.adapter = adapter
trackSelectedItems(adapter, binding.recycleView)
adapter.notifyDataSetChanged()
})
binding.btnGoToNextFragment.setOnClickListener {
val action = MainFragmentDirections.actionMainFragmentToOtherFragment()
findNavController().navigate(action)
}
return binding.root
}
private fun trackSelectedItems(
adapter: MyListAdapter,
recyclerView: RecyclerView
) {
tracker = SelectionTracker.Builder<String>(
"selectionTracker",
recyclerView,
ItemIdKeyProvider(adapter),
ItemLookup(recyclerView),
StorageStrategy.createStringStorage()
).withSelectionPredicate(SelectionPredicates.createSelectAnything())
.build()
adapter.setTracker(tracker)
tracker.addObserver(object : SelectionTracker.SelectionObserver<String>() {
override fun onSelectionChanged() {
super.onSelectionChanged()
}
})
}
Steps to reproduce:
Open first fragment with recycleview, try to select/deselect items. Everything works fine
Go to another fragment, then press back button
Try to select/deselect items again and you'll see that deselection doesn't work anymore
Don't initialize adapter inside live data's observer. Because Live Data might be observed n number of times, so if you initialize adapter inside that, adapter will be initialized many times.
To resolve issue use below code
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
viewModel = createViewModel()
binding = DataBindingUtil.inflate(inflater, R.layout.main_fragment, container, false)
binding.viewModel = viewModel
binding.lifecycleOwner = this
viewModel.initViewModel()
val adapter = MyListAdapter()
binding.recycleView.adapter = adapter
trackSelectedItems(adapter, binding.recycleView)
//adapter.notifyDataSetChanged()
viewModel.items.observe(this, Observer { items ->
adapter.submitList(items)
})
binding.btnGoToNextFragment.setOnClickListener {
val action = MainFragmentDirections.actionMainFragmentToOtherFragment()
findNavController().navigate(action)
}
return binding.root
}
I make an api call to get a list, in the logcat I can see all the groups that came back from the api but the Recylerview doesn't show my items.
ViewModel
class MyGroupScreenViewMode(private val context: Context, private val codagramApi: CodagramApi) : ViewModel() {
#ExperimentalCoroutinesApi
private val myGroups = MutableLiveData<List<Group>>()
#ExperimentalCoroutinesApi
fun getMyGroups(): LiveData<List<Group>> = myGroups
init {
viewModelScope.launch(Dispatchers.IO){
val response = codagramApi.getAllGroups()
updateUi(response.groupList)
}
}
#ExperimentalCoroutinesApi
private fun updateUi(update: List<Group>){
viewModelScope.launch(Dispatchers.Main){
myGroups.value = update
}
}
and the fragment
class MyGroupScreen : Fragment() {
private val myGroupsAdapter: GroupAdapter by inject()
private lateinit var bindingGroup: FragmentThirdBinding
#ExperimentalCoroutinesApi
private val viewModel: MyGroupScreenViewMode by inject()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
bindingGroup = FragmentThirdBinding.inflate(layoutInflater, container, false)
return bindingGroup.root
}
#ExperimentalCoroutinesApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bindingGroup.myGroups.apply {
adapter = this#MyGroupScreen.myGroupsAdapter
layoutManager = LinearLayoutManager(context)
}
myGroupsAdapter.currentList
bindingGroup.fabAdd.setOnClickListener {
it.findNavController().navigate(MyGroupScreenDirections.actionFirstViewToGroupscreen())
}
bindgetmyGroupToLiveData()
}
#ExperimentalCoroutinesApi
private fun bindgetmyGroupToLiveData() {
viewModel.getMyGroups().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
myGroupsAdapter.submitList(it)
})
}
and the adapter
class GroupAdapter : ListAdapter<Group,GroupScreenViewHolder>(object: DiffUtil.ItemCallback<Group>(){
override fun areItemsTheSame(oldItem: Group, newItem: Group): Boolean = oldItem.creator?.id == newItem.creator?.id
override fun areContentsTheSame(oldItem: Group, newItem: Group): Boolean =
oldItem == newItem
}) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroupScreenViewHolder {
return GroupScreenViewHolder(
GroupscreenMygroupsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
#RequiresApi(Build.VERSION_CODES.N)
override fun onBindViewHolder(holder: GroupScreenViewHolder, position: Int) {
holder.bind(getItem(position))
}
}
class GroupScreenViewHolder(private val binding: GroupscreenMygroupsBinding) :
RecyclerView.ViewHolder(binding.root) {
#RequiresApi(Build.VERSION_CODES.N)
fun bind(postData: Group) {
binding.textView.text = postData.id.toString()
}
}
Check if data is in the list, then assign the list to adapter and call adapter.notifyDataSetChanged(),