Home > OS >  Stateflow collect multiple times inside each button click event. How to resolve this issue?
Stateflow collect multiple times inside each button click event. How to resolve this issue?

Time:09-19

I checked and found that collects have been increased two times by each click . I don't know what is the cause and what is the remedy for below code . I am a beginner in Android dev and this issue becomes a headache for me.

 binding.downloadBtn.setOnClickListener {
        var count = 0
        if (id != null) {       
            viewModel.getDownloads(id)
        }
        lifecycleScope.launch {
               viewModel.getDownloads.collect {
                    count  
                    Log.i("torrent movies", "count ${count} and download ${it}")               
                    if (downloads!=null) {
                       bundle.putParcelable(Constants.DOWNLOADS, downloads)
                       findNavController()
                            .navigate(R.id.action_movieDetailsFragment_to_downloadFragment, bundle)
                    }
               }
        }
 }

CodePudding user response:

Your count variable and viewModel.getDownloads.collect {} this code should be outside of onClick(). In your current code everytime user is performing click we are setting the collect

CodePudding user response:

I believe previous coroutine should be cancelled before launching a new one. If the previous coroutine is not cancelled then collecting of data will not stop for previous button click:

var job: Job? = null

binding.downloadBtn.setOnClickListener {
    var count = 0
    if (id != null) {       
        viewModel.getDownloads(id)
    }
    job?.cancel()
    job = lifecycleScope.launch {
           viewModel.getDownloads.collect {
                count  
                Log.i("torrent movies", "count ${count} and download ${it}")               
                if (downloads!=null) {
                   bundle.putParcelable(Constants.DOWNLOADS, downloads)
                   findNavController()
                        .navigate(R.id.action_movieDetailsFragment_to_downloadFragment, bundle)
                }
           }
      }
}

CodePudding user response:

It's not a good practice to write the collect block into onClickListener. Because each time you click on the button, it will start a new collecting block.

If you need the value of getDownloads after clicking on the button you should use first() to get the value immediately and navigate to the next page.

I think you can use this code and check if it is what you want.

binding.downloadBtn.setOnClickListener {
        var count = 0
        if (id != null) {
            viewModel.getDownloads(id)
        }
        lifecycleScope.launch {
            val downloadCount = viewModel.getDownloads.first()
                count  
                Log.i("torrent movies", "count $count and download $downloadCount")
                if (downloads != null) {
                    bundle.putParcelable(Constants.DOWNLOADS, downloads)
                    findNavController()
                        .navigate(R.id.action_movieDetailsFragment_to_downloadFragment, bundle)
            }
        }
    }
  • Related