从数据库中导入的数据未设置
我正在制作与图像类似的屏幕。
提前从Room db
中获取数据集,并为每个选项卡设置数据集。
每个选项卡为fragment
,并在recyclerview
中显示数据。
每个选项卡都包含不同的数据,因此我将选项卡设置为livedata
in viewModel
并观察它。
因此,每当选项卡更改时,目标是从数据库中获取每个选项卡的数据,并在recyclerview
中设置它。
但是,即使我导入数据,也没有在recyclerview中设置它。
我认为即使在调试数据时,数据也很顺利。
这不是适配器问题。
我想念什么?
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
}
}
存储库
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
}
}
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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您看到的问题是,在
setList
中,您在IO线程上启动异步的coroutine以获取列表,但是您实际上并没有等待该coroutine运行,而只需立即返回空列表。修复的一种方法是观察一个包含列表的寿命对象,而不是观察零件。然后,当异步任务完成时
您可以将检索到的数据发布到该Livedata。然后在视图模型中看起来像这样,
然后在片段
increateview
中观察列表,当值更改时,您将它们添加到适配器中。如果值可能会发生多次变化,则可能需要清除适配器,然后再添加观察者内部的项目。note :文档当前仅建议在
increateview
中仅夸大视图并在<代码中进行所有其他设置和初始化> onviewCreated - 我将其保留在问题中以保持一致性。The problem you are seeing is that in
setList
you start an asynchronous coroutine on the IO thread to get the list, but then you don't actually wait for that coroutine to run but just return the empty list immediately.One way to fix that would be to observe a LiveData object containing the list, instead of observing the part. Then, when the asynchronous task is complete
you can post the retrieved data to that LiveData. That would look like this in the view model
Then in the fragment
onCreateView
you observe the list, and when the values change you add them to the adapter. If the values may change several times you may need to clear the adapter before adding the items inside the observer.Note: The documentation currently recommends only inflating views in
onCreateView
and doing all other setup and initialization inonViewCreated
- I kept it how you had it in your question for consistency.