Search code examples
kotlinonclicklistenerkotlin-coroutines

Can't add a suspended function to a setOnClickListener in my AlertDialog


The add_button in the songToAddDialog() method won't accept my suspended method positiveButtonClick() into its setOnClickListener. I have been looking to this for hours and I do not know what to do.

// Check the GenreKey of the current playlist to use later to create the Song
    suspend fun playlistGenreCheck(id: Long): Long {
        val playlist = dataSource.getPlaylist(id)
        val playlistGenre = playlist.playlistGenre
        return playlistGenre
    }

    // When you press the add button in the AlertDialog it will add the song to the database and closes the AlertDialog afterwards
    suspend fun positiveButtonClick(builder: AlertDialog){
        val song = Song(title = builder.dialogTitleEt.toString(), artist = builder.dialogArtistEt.toString(), playlist = arguments.playlistKey, key = builder.dialogKeyEt.toString(), genre = playlistGenreCheck(arguments.playlistKey))
        songsModel.addSong(song)
        builder.dismiss()
    }

    // When you press the cancel button the AlertDialog will bet dismissed
    fun negativeButtonClick(builder: AlertDialog){
        builder.dismiss()
    }

    // This creates the AlertDialog and adds the two functions above to the buttons
    fun songToAddDialog(){
        val mDialogView = LayoutInflater.from(requireContext()).inflate(R.layout.add_song_dialog, null)
        val mBuilder = AlertDialog.Builder(requireContext()).setView(mDialogView).setTitle("Add a Song")
        val mAlertDialog = mBuilder.show()

        mDialogView.add_button.setOnClickListener{positiveButtonClick(mAlertDialog)}
        mDialogView.cancel_button.setOnClickListener{negativeButtonClick(mAlertDialog)}
    }

    // Makes the add-button inside the songslistview observable
    songsModel.addButton.observe(viewLifecycleOwner, androidx.lifecycle.Observer{
        if (it) {
            songToAddDialog()
        }
    })

Solution

  • The Suspend function can only be called from a CoroutineScope. If you have the lifecycle dependency then use:

    mDialogView.add_button.setOnClickListener{
    
          lifecyclescope.launch{
    
             positiveButtonClick(mAlertDialog)
          
          }
    }
    

    If you don't have lifecycle dependencies then calling CoroutineScope like this should also work:

    mDialogView.add_button.setOnClickListener{
    
          CoroutineScope(Dispatchers.IO).launch{
    
             positiveButtonClick(mAlertDialog)
          
          }
    }
    

    Do tell if you still have some problem regarding this :)