Alex Rodionow
Alex Rodionow

Reputation: 257

How to combine 2 Flows as to pass their values as arguments into suspend fun (which returns String)?

Before, when the "suspend fun getCategoryName(categoryNumber: Int)" function in ViewModel contained only one argument - categoryNumber: Int, I used to lounch it this way in Fragment:

In Fragment:

viewModel.categoryNumber.observe(viewLifecycleOwner) {
        viewLifecycleOwner.lifecycleScope.launch {
            (activity as MainActivity).supportActionBar?.title = viewModel.getCategoryName(it)
        }
    }

Now I added the second argument NativeLanguage (enum), and I don't understant how to combine both argumnets and pass them into the one method to lounch it in Fragment. Could sombodey help please? Appreciate any help.

PS i tried ti type somthg like that:

suspend fun catName(): String = combine( catNumFlow, natLangFlow ) { cN, nL ->
        Pair(cN, nL)
    }.flatMapLatest { (cN, nL) ->
        wordDao.getCategoryName(cN, nL)
    }

But here is type mismatch, cause Dao function is a suspend fun returning String, whereas combine of 2 Flows returns Flow.

Also I tried just put one observer into another, and it works wierd:

viewModel.readNatLang.observe(viewLifecycleOwner) { natLang ->
    viewModel.categoryNumber.observe(viewLifecycleOwner) { catNum ->
        viewLifecycleOwner.lifecycleScope.launch {
            (activity as MainActivity).supportActionBar?.title =
                viewModel.getCategoryName(catNum, natLang)
            }
        }
    }
}

In ViewModel:

val catNumFlow = preferencesManager.categoryNumberFlow // returns Flow<Int>
private val natLangFlow = preferencesManager.nativeLanguageFlow // Flow<NativeLanguage> (enum)

suspend fun getCategoryName(categoryNumber: Int, nativeLanguage: NativeLanguage) = wordDao.getCategoryName(categoryNumber, nativeLanguage)

My Dao query:

suspend fun getCategoryName(categoryNumber: Int, nativeLanguage: NativeLanguage) =
    if (categoryNumber != 0) {
        when (nativeLanguage) {
            NativeLanguage.RUS -> getCategoryNameRus(categoryNumber)
            NativeLanguage.ENG -> getCategoryNameEng(categoryNumber)
        }
    } else {
        when (nativeLanguage) {
            NativeLanguage.RUS -> "Все категории"
            NativeLanguage.ENG -> "All categories"
        }
    }

@Query("SELECT categoryNameRus FROM category_table WHERE categoryNumber = :categoryNumber")
suspend fun getCategoryNameRus(categoryNumber: Int): String

@Query("SELECT categoryNameEng FROM category_table WHERE categoryNumber = :categoryNumber")
suspend fun getCategoryNameEng(categoryNumber: Int): String

Upvotes: 1

Views: 1818

Answers (1)

Louis Wasserman
Louis Wasserman

Reputation: 198311

From what it looks like, you shouldn't be returning String, you should be returning Flow<String>, and collecting it:

suspend fun getCategoryNameFlow(): Flow<String> = combine( catNumFlow, natLangFlow ) { 
  cN, nL -> wordDao.getCategoryName(cN, nL)
}

...and then you should collect that flow

launch {
  getCategoryNameFlow().collect { name ->
     (activity as MainActivity).supportActionBar?.title = name
  }
}

...which will update the title whenever one of the other flows updates.

Upvotes: 2

Related Questions