I'm making a screen similar to the image.
The data set in advance is taken from the Room DB and the data is set for each tab.
Each tab is a fragment and displays the data in a RecyclerView.
Each tab contains different data, so i set Tab to LiveData in ViewModel and observe it.
Therefore, whenever tabs change, the goal is to get the data for each tab from the database and set it in the RecyclerView.
However, even if I import the data, it is not set in RecyclerView.
I think the data comes in well even when I debug it.
This is not an adapter issue.
What am I missing?
WorkoutList
@Entity
data class WorkoutList(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val chest: List<String>,
val back: List<String>,
val leg: List<String>,
val shoulder: List<String>,
val biceps: List<String>,
val triceps: List<String>,
val abs: List<String>
)
ViewModel
class WorkoutListViewModel(application: Application) : AndroidViewModel(application){
private var _part :MutableLiveData<BodyPart> = MutableLiveData()
private var result : List<String> = listOf()
private val workoutDao = WorkoutListDatabase.getDatabase(application).workoutListDao()
private val workoutListRepo = WorkoutListRepository(workoutDao)
val part = _part
fun setList(part : BodyPart) : List<String> {
_part.value = part
viewModelScope.launch(Dispatchers.IO){
result = workoutListRepo.getWorkoutList(part)
}
return result
}
}
Repository
class WorkoutListRepository(private val workoutListDao: WorkoutListDao) {
suspend fun getWorkoutList(part: BodyPart) : List<String> {
val partList = workoutListDao.getWorkoutList()
return when(part) {
is BodyPart.Chest -> partList.chest
is BodyPart.Back -> partList.back
is BodyPart.Leg -> partList.leg
is BodyPart.Shoulder -> partList.shoulder
is BodyPart.Biceps -> partList.biceps
is BodyPart.Triceps -> partList.triceps
is BodyPart.Abs -> partList.abs
}
}
}
Fragment
class WorkoutListTabPageFragment : Fragment() {
private var _binding : FragmentWorkoutListTabPageBinding? = null
private val binding get() = _binding!!
private lateinit var adapter: WorkoutListAdapter
private lateinit var part: BodyPart
private val viewModel: WorkoutListViewModel by viewModels()
companion object {
@JvmStatic
fun newInstance(part: BodyPart) =
WorkoutListTabPageFragment().apply {
arguments = Bundle().apply {
putParcelable("part", part)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let { bundle ->
part = bundle.getParcelable("part") ?: throw NullPointerException("No BodyPart Object")
}
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
_binding = FragmentWorkoutListTabPageBinding.inflate(inflater, container, false)
binding.apply {
adapter = WorkoutListAdapter()
rv.adapter = adapter
}
val result = viewModel.setList(part)
// Set data whenever tab changes
viewModel.part.observe(viewLifecycleOwner) { _ ->
// val result = viewModel.setList(part)
adapter.addItems(result)
}
return binding.root
}
} viewModel.part.observe(viewLifecycleOwner) { _ ->
adapter.addItems(result)
}
return binding.root
}
}

setListis asynchronous and the function returns the empty list before the coroutine actually runs to populate it. Try making the list a LiveData, posting the db data to it in the coroutine instead of returning the list, and observing it and populating the adapter in the observer.setLista suspend function and call it from a coroutine in the part observer.partas both live data in the view model and as a class member in the fragment will probably lead to trouble with inconsistent state. The view model should hold the single source of truth/state. When you read the part from the bundle you should pass that to the view model instead of saving it as a class member.