Search code examples
androidkotlinrx-javareactive-programmingrx-android

Get list from Single<List> observable


I have a method which returns Single<List<HistoryItem>>. Now I want to get list from this.

private fun getListOfDownload(): ArrayList<HistoryItem> {
    val downloads = manager.lastHundredVisitedHistoryItems()
    downloads.subscribe { t ->
        return t; // not allowed
    }
}

I could use subscribe but that does not allow me to return list from that.

I tried map also.

downloads.map { t: List<HistoryItem> -> return t } // again `return t` is not allowed.

Edit

I could make this work by following

private fun getListOfDownload(): ArrayList<HistoryItem> {
        var list = ArrayList<HistoryItem>()
        val downloads = manager.lastHundredVisitedHistoryItems()
        downloads.subscribe { t ->
            list = t as ArrayList<HistoryItem>
        }
        return list
    }

Please tell

  • If this way is right & will it not block main thread?
  • Is there not a way to return the list without declaring another list?

I am new to Reactive programming so please explain me.


Solution

  • In your code getListOfDownload is returning the ArrayList<HistoryItem>, while lastHundredVisitedHistoryItems of manager returning Single<ArrayList<HistoryItem>> which means the you want to observe ArrayList<HistoryItem>, becuase lastHundredVisitedHistoryItems gonna take some times.

    that's why you can not return the item in subscribe block because that block is lamda which is going to observe ArrayList<HistoryItem> item.

    But if you don't care about the observation you can do something like this,

    private fun getListOfDownload(): ArrayList<HistoryItem> {
        val downloads = manager.lastHundredVisitedHistoryItems()
        return downloads.blockingGet()
    }
    

    But you are loosing the asynchronus call of lastHundredVisitedHistoryItems as we are applying blockingGet(), but as you are not observing it on seperate thread i am assuming that you want to call it on main thread.

    But if you want to observe lastHundredVisitedHistoryItems() then you can pass the method as a parameter which will act as cosumer for ArrayList<HistoryItem>.

    private fun getListOfDownload( listener : (ArrayList<LoginViewModel.HistoryItem>) -> Unit) {
            val downloads = manager.lastHundredVisitedHistoryItems()
            downloads.subscribe { t -> listener.invoke(t) }
    }
    
    // when you call above method look like below
    // here variable `it` is nothing but a object of ArrayList<LoginViewModel.HistoryItem>
    getListOfDownload { adapter.updateDataSet(it) }