0

I'm trying to rewrite my program and start using Kotlin Coroutines. That is my function to retrieve a list of products for a given group. After debugging it looks like everything is correct.

class FirebaseRepository {

    private val db = FirebaseFirestore.getInstance()
    private val auth = FirebaseAuth.getInstance()

    fun getCurrentUserId(): String{
        return auth.currentUser!!.uid
    }

    suspend fun getLista(): MutableLiveData<List<Produkt>> {
        val result = MutableLiveData<List<Produkt>>()
        val lista = mutableListOf<Produkt>()
        db.collection(Constants.GROUP)
            .document("xGRWy21hwQ7yuBGIJtnA")
            .collection("Przedmioty")
            .orderBy("dataDodaniaProduktu", Query.Direction.DESCENDING)
            .get().await().forEach {

                val singleProdukt = it.toObject(Produkt::class.java)
                singleProdukt.produktId = it.id
                lista.add(singleProdukt)
                result.postValue(lista)
            }
        return result
    }

That is my ViewModel class:

    class ListaViewModel: ViewModel() {

    private val repository = FirebaseRepository()
    var _produkty =  MutableLiveData<List<Produkt>>()
    val produkty : LiveData<List<Produkt>> = _produkty


    init {
        viewModelScope.launch {
            _produkty = repository.getLista()
        }
    }

And finally in my fragment I'm trying to observe live data but looks like nothing is being passed to my adapter. What am I doing wrong?

class ListaFragment : Fragment(), ListaAdapter.OnItemClickListener {

    private var _binding: FragmentListaBinding? = null
    private val binding get() = _binding!!
    private lateinit var recyclerView : RecyclerView

    private lateinit var listAdapter : ListaAdapter
    private val listaViewModel by viewModels<ListaViewModel>()


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentListaBinding.inflate(inflater, container, false)
        recyclerView = binding.recyclerView

        listAdapter = ListaAdapter(emptyList(), this)
        recyclerView.adapter = listAdapter // Zapobiega "No adapter attached; skipping layout"
        recyclerView.layoutManager = LinearLayoutManager(requireActivity())
        recyclerView.setHasFixedSize(true)
    
     listaViewModel.produkty.observe(viewLifecycleOwner, Observer {
            listAdapter = ListaAdapter(it, this)
    }
    return binding.root
    }
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Johnny
  • 1
  • 1

2 Answers2

0

Try replacing this:

val produkty : LiveData<List<Produkt>> = _produkty

with this

val produkty : LiveData<List<Produkt>> get() = _produkty

This way you'll have "getter" rather than "initializer". Initializer will compute its value once (to the empty live data) and after you reassign that var it won't change the value of your val.

dimsuz
  • 8,969
  • 8
  • 54
  • 88
  • Unfortunetly it didn't help. Without coroutines i had similar function in class FirebaseRepository but instead await i have used addSnapshotListener. Then in my view holder i called simple _repository.getLista("id")_ and everything worked well. – Johnny May 25 '22 at 23:07
  • Then perhaps you subscribe after you emit a value, and so it gets lost? I'm not that familiar with LiveData and ViewModels (we use Flow and do not use ViewModels from Google), so maybe put some log statements in places where you emit/observe values and check the order. – dimsuz May 26 '22 at 00:53
0

The problem in your code lies in the fact that you're creating a new instance of your ListaAdapter class inside the observe() method, without notifying the adapter about the changes. That's the reason why you're getting no results in the adapter. To solve this, simply create a method inside your adapter class:

fun setProduktList(produktList: List<Produkt>) {
    this.produktList = produktList
    notifyDataSetChanged()
}

Then inside your observe() method, use the following line of code:

listaViewModel.produkty.observe(viewLifecycleOwner, Observer {
    //listAdapter = ListaAdapter(it, this) //Removed
    listAdapter.setProduktList(it) 
}
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193