【发布时间】:2020-02-21 19:37:58
【问题描述】:
我想请你帮忙。我正在编写一个使用 MVVM 和 LiveData 架构的应用程序。在 ViewPager 中,我有 3 个片段显示来自 ViewModel 的数据。而且我注意到,在将 viewModel 连接到 Activity 和 Fragment 之后,只有在 Activity 启动时才会更新数据,但是即使数据发生了变化,Observe 也不会更新数据。在向服务器调用下一个查询后,在 onDataSet 中,我发送适当的时间并从服务器获取 JSON 数据,然后解析并传递给 ViewModel。为什么 Fragment 一开始只更新一次数据,之后就什么都没有了?
这是托管片段的活动
class MainActivity : AppCompatActivity(), DatePickerDialog.OnDateSetListener {
private lateinit var currencyViewModel: CurrencyViewModel
private lateinit var viewPager: ViewPager2
private lateinit var tabLayout: TabLayout
private lateinit var navigationView: NavigationView
private lateinit var floatingActionButton: FloatingActionButton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val fm = supportFragmentManager
currencyViewModel = ViewModelProvider
.AndroidViewModelFactory(application)
.create(CurrencyViewModel::class.java)
viewPager = findViewById(R.id.viewPager)
tabLayout = findViewById(R.id.tabLayout)
navigationView = findViewById(R.id.navigationView)
floatingActionButton = findViewById(R.id.floatingActionButton)
val viewPagerAdapter = CurrencyViewPagerAdapter(this)
viewPager.adapter = viewPagerAdapter
TabLayoutMediator(tabLayout
,viewPager
,TabLayoutMediator.TabConfigurationStrategy {
tab, position ->
when(position){
0 -> tab.text = "Tabela A"
1 -> tab.text = "Tabela B"
2 -> tab.text = "Tabela C"
}
}).attach()
floatingActionButton.setOnClickListener {
val dialog = CalendarFragment()
dialog.show(fm, "DatePickerDialog")
}
}
override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
//Convert year,month,day to millisecounds
val c = Calendar.getInstance()
c.set(year,month,dayOfMonth)
val dayInMillis = c.time.time
val today = Calendar.getInstance()
if(checkIsDateAfterToday(today, c)){
CoroutineScope(Dispatchers.Main).launch {
currencyViewModel.setTableA(dayInMillis)
}
}
}
这是 Activity 和 Fragment 通用的 ViewModel
class CurrencyViewModel : ViewModel() {
private val repository = CurrencyRepository()
val tableA: MutableLiveData<Array<TableA>> by lazy {
MutableLiveData<Array<TableA>>().also {
loadTableA(Date().time)
}
}
private fun loadTableA(time: Long) {
CoroutineScope(Dispatchers.Main).launch {
val loadedData = CoroutineScope(Dispatchers.IO).async {
repository.getTableA(time)
}.await()
tableA.value = loadedData
}
}
fun setTableA(time: Long){
loadTableA(time)
}
}
这就是在recyclerView中显示数据的片段
class TableAFragment : Fragment() {
private lateinit var currencyViewModel: CurrencyViewModel
private lateinit var recyclerViewA: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_table_a, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
currencyViewModel = ViewModelProvider.AndroidViewModelFactory
.getInstance(requireActivity().application)
.create(CurrencyViewModel::class.java)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerViewA = view.findViewById(R.id.recyclerView_A)
recyclerViewA.layoutManager = LinearLayoutManager(requireContext())
currencyViewModel.tableA.observe(viewLifecycleOwner, androidx.lifecycle.Observer{
val nbpAdapter = NBPAdapter(it)
recyclerViewA.adapter = nbpAdapter
})
}
}
【问题讨论】:
标签: android kotlin mvvm android-livedata