【发布时间】:2022-01-11 12:57:05
【问题描述】:
我很难在 MVVM 模式上使用实时数据。该应用程序应该:
- 从 API 获取数据(它正确)
- 将该数据存储在 ViewModel 的 Live data 对象中
- 然后fragment调用Observer方法填充recyclerView。
问题出现在第 3 点,它什么也没做,我找不到解决方案。
这里是相关代码。 (如有遗漏,我会尽快回复)
主要活动:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val viewModel: SharedViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Custom button to fetch data from api and log the Live Data value.
binding.refreshFab.setOnClickListener {
viewModel.fetchPlayerData()
Log.d("gabs", "${viewModel.livePlayerlist.value}")
}
}
}
视图模型:
class SharedViewModel(app: Application): AndroidViewModel(app) {
// val playerDao = LaRojaDB.getDatabase(app).playerDao()
lateinit var playerList: Players
val livePlayerlist: MutableLiveData<MutableList<Players.PlayersItem>> by lazy {
MutableLiveData<MutableList<Players.PlayersItem>>()
}
fun fetchPlayerData() {
CoroutineScope(Dispatchers.IO).launch {
val response = MyService.getLaRojaService().getAllPlayers()
withContext(Dispatchers.Main) {
if (response.isSuccessful) {
val body = response.body()
if(!body.isNullOrEmpty()){
playerList = body
val playerArrayList = mutableListOf<Players.PlayersItem>()
playerList.forEach {
playerArrayList.add(it)
}
livePlayerlist.value = playerList
}
}
}
}
}
}
显示回收器视图的片段:(片段已经显示,我设置了一个 textView 作为标题,以确保我也是新使用片段。)
class PlayerListFragment : Fragment() {
private var _binding: FragmentPlayerListBinding? = null
private val binding get() = _binding!!
private val model: SharedViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentPlayerListBinding.inflate(inflater, container, false)
binding.rvPlayerList.layoutManager = LinearLayoutManager(activity)
----> // This is the observer that does not update the UI** <----
model.livePlayerlist.observe( viewLifecycleOwner, {
binding.rvPlayerList.adapter = PlayerAdapter(it)
})
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_player_list, container, false)
}
}
提前谢谢大家,希望我终于可以知道是什么导致了这个问题!
【问题讨论】:
-
实际观察者是否被调用?如果你放一个断点,它会命中吗?如果有,它是否包含您期望的数据?如果是这样,那么您可能遇到了适配器问题。如果没有,那么我们将需要更多关于这个 sharedVM 是如何设置的信息。
-
你为什么要切换到主上下文呢?你应该留在 IO 并做
livedata.postValue(...)而不是livedata.value = ... -
我终于找到了解决方案,我按照您所说的做了,首先将 LiveData 更改为 Sealed 类,然后,由于问题仍然存在,我按照您在此 cmets 中提到的条件...事实证明,正如您所指出的,我没有将数据正确地发送到适配器,我在某个不属于的地方有代码。 (了解片段是如何工作的:我将代码放在方法 onCreateView 而不是 onViewCreated 中!)。非常感谢,对我帮助很大!
-
祝你好运!很高兴听到它起作用了 ;)
标签: android-studio kotlin android-fragments mvvm android-livedata