Rejfi
Rejfi

Reputation: 25

LiveData doesn't update data

I would like to ask you for help. I am writing an application that uses MVVM and LiveData architecture. Inside ViewPager I have 3 fragments displaying data that comes from ViewModel. And I noticed that after connecting the viewModel to the activity and to the fragment, the data is updated only when the activity is started, but then Observe does not update the data even though the data has changed. After calling the next query to the server, inside onDataSet I send the appropriate time and obtains JSON data from the server, which it parses and passes to ViewModel. Why Fragment updates data only once in the beginning and nothing changes after?

This is the activity that hosts the fragments

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)
            }
        }

    }

This is ViewModel common for activity and fragment

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)
   }

}

And that's the fragment which displays data in 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
        })

    }

}

Upvotes: 0

Views: 1148

Answers (1)

EpicPandaForce
EpicPandaForce

Reputation: 81539

Your instantiation of ViewModel is incorrect.

Should be

currencyViewModel = ViewModelProvider(this).get<CurrencyViewModel>() // lifecycle-ktx

and in Fragment:

currencyViewModel = ViewModelProvider(requireActivity()).get<CurrencyViewModel>() // lifecycle-ktx

Upvotes: 2

Related Questions