简体   繁体   中英

Android LiveData: How to do an ArrayList<LiveData<RetrofitObject>>?

I am creating an app with MVVM architecture and I ran into an issue of getting a list of LiveData to show in the View.

In my ViewModel I have a getAll() function that retrieves a list of strings from the database using Room. From there, I get the strings and call my Retrofit function to send each string individually to a web-server that returns an object. Here is where my issue occurs.

From the MVVM tutorials I see online, they usually have the LiveData> style but in this since I am getting each object individually, it becomes List> but I don't think this is the correct way of doing it because in my View I would need to do a ForEach loop to observe each LiveData object in the list.

I have tried other work arounds but it doesn't seem to work. Is there a better way of doing this?

DAO

@Query("SELECT * FROM table")
    fun getAll(): LiveData<List<String>>

Repository

fun getAll(): LiveData<List<String>> {
        return dao.getAll()
    }

fun getRetrofitObject(s: String): LiveData<RetrofitObject> {
        api = jsonApi.getRetrofitObjectInfo(s, API_KEY)
        val retrofitObject: MutableLiveData<RetrofitObject> = MutableLiveData()
        api.enqueue(object : Callback<RetrofitObject> {
            override fun onFailure(call: Call<RetrofitObject>?, t: Throwable?) {
                Log.d("TEST", "Code: " + t.toString())
            }

            override fun onResponse(call: Call<RetrofitObject>?, response: Response<RetrofitObject>?) {
                if (response!!.isSuccessful) {
                    retrofitObject.value = response.body()
                }
            }
        })
        return retrofitObject
    }

MainActivityViewModel (ViewModel)

var objectList ArrayList<LiveData<retrofitObject>> = ArrayList() 

// This is getting objects using Retrofit
fun getRetrofitObject(s: String): LiveData<retrofitObject> {
        return repo.getRetrofitObject(s)
    }

// This is getting all the strings from the internal database
fun getAll(): ArrayList<LiveData<retroFitObject>> {
        repo.getAll().value?.forEach {it ->
            objectList.add(getRetrofitObject(it)) //How else would I be able to do this?
        }
        return objectList
    }

MainActivity (View)

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mainActivityViewModel.getAll().forEach {
                        it.observe(this, Observer {it ->
                            mainActivityViewModel.objectList.add(it) //Here is part of the issue since I don't want to use a forloop in the View

                        })
                    }
                    adapter.objectList = mainActivityViewModel.objectList
                    recyclerView.adapter = adapter
}

Thanks, let me know if there is anything else needed or confusion!

By looking at the above code you are trying to fetch a list of item for each table row from server and and trying to update the result to your recycler view. Your logic is little confusing.. So on your activity.. first init your adapter and recyclerview

Then call your viewmodel function to get all values inside table and make a loop to call your network thread fuction in background and store the values in a live data object.

Just observe this livedata in your activity/fragment and just pass the list to adapter and notify it.by doing this,whenever your livedata got a change your recyclerview also reflect the items

The problem with your code is, you are called a retrofit network function with enque option and its a background thread process.so, code wont wait for the network completion. And it will return the retrofitObject data.but it has not got the data yet.so this will make error.

There might be other methods exist I don't know about them.

But you can deal with situation using Transformations for more information please look at documentation page. Transformations.switchMap(LiveData trigger, Function> func)

You don't have to put the live data observer inside for loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM