I am working on an app which has a RecyclerView inside a Fragment. The objective of the Fragment, is to fetch with a cursor Tracks's data. Since this process is long, I decide to implement a ViewModel, using a coroutine to let the processes work faster.
However, I have a problem with this: the coroutine doesn't always start as it should. For some reason, when I open the app, sometimes the coroutine executes as soon as the Fragment gets opened, showing then the proper data inside the RecyclerView, and sometimes it doesn't.
What happens (left) and what should happen (right):
What is happening? Is there a way to fix this?
Fragment.kt
class FragmentTrack : Fragment(), AdapterOneColumn.OnItemClickListener {
var trackList = mutableListOf<DataItems>()
....
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
....
if(trackList.isEmpty()) {
val cttResolver : ContentResolver? = activity?.contentResolver
ViewModelCycleTracks().recyclerNeedsTracks(trackList, cttResolver)
}
rvTracks.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(activity)
adapter = AdapterOneColumn(trackList, this@FragmentTrack)
}
}
override fun OnItemClick(position: Int) {
Toast.makeText(context, "Pressed song", Toast.LENGTH_SHORT).show()
}
}
ViewModel.kt
class ViewModelCycleTracks : ViewModel() {
fun recyclerNeedsTracks(trackList: MutableList<DataItems>, cttResolver: ContentResolver?) {
viewModelScope.launch {
cycleFiles(trackList, cttResolver)
}
}
suspend fun cycleFiles(trackList: MutableList<DataItems>, cttResolver: ContentResolver?) {
return GlobalScope.async(Dispatchers.IO) {
var songCursor : Unit? = cttResolver?.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null, null, null, null)?.use {cursor ->
val idSongName = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)
val idSongArtist = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)
val idSongArt = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID)
while (cursor.moveToNext()) {
val songName = cursor.getString(idSongName)
val songArtist = cursor.getString(idSongArtist)
val songArt = cursor.getString(idSongArt)
trackList.add(DataItems(songName, songArtist))
}
}
}.await()
}
}

