Suspension functions can be called only within coroutine body

I checked the other questions but none of them seem to address my issue. I have two suspend funs in my HomeViewModel and I’m calling them in my HomeFragment (with a spinner text parameter).

The two suspend functions in HomeViewModel:

suspend fun tagger(spinner: Spinner){
       withContext(Dispatchers.IO){
           val vocab: String = inputVocab.value!!
           var tagger = Tagger(
                   spinner.getSelectedItem().toString() + ".tagger"
           )
           val sentence = tagger.tagString(java.lang.String.valueOf(vocab))
           tagAll(sentence)
       }
    }


    suspend fun tagAll(vocab: String){
       withContext(Dispatchers.IO){
           if (inputVocab.value == null) {
               statusMessage.value = Event("Please enter sentence")
           }
           else {
               insert(Vocab(0, vocab))
               inputVocab.value = null
           }
       }
    }

and this is how I call them in the HomeFragment:

GlobalScope.launch (Dispatchers.IO) {
        button.setOnClickListener {
            homeViewModel.tagger(binding.spinner)
        }
    }

At tagger I get the error “Suspension functions can be called only within coroutine body”. But it’s already inside a global scope. How can I avoid this problem?

Answer

But it’s already inside a global scope.

The call to button.onSetClickListener() is in a launched coroutine from a CoroutineScope. However, the lambda expression that you are passing to onSetClickListener() is a separate object, mapped to a separate onClick() function, and that function call is not part of that coroutine.

You would need to change this to:

    button.setOnClickListener {
        GlobalScope.launch (Dispatchers.IO) {
            homeViewModel.tagger(binding.spinner)
        }
    }

BTW, you may wish to review Google’s best practices for coroutines in Android, particularly “The ViewModel should create coroutines”.

Leave a Reply

Your email address will not be published. Required fields are marked *