Search code examples
androidandroid-asynctasktogglebutton

Android ToggleButton - do something while enabled without locking up UI thread


What I want to do is run a method that will play a random sound from my assets while a ToggleButton is On. And then stop doing that when the ToggleButton is Off. The problem is that as currently constructed, my code locks up with UI thread. I thought I was using AsyncTask correctly, but apparently not.

Can you suggest either a fix for this or a better method to accomplish what I want?

    public void onToggleClicked(View view) {
    // Is the toggle on?
    boolean on = ((ToggleButton) view).isChecked();



    while (on) {

        AssetManager assetMgr = this.getAssets();
        try {
            String[] filename = assetMgr.list("sounds");
            Random r = new Random();
            String fn = filename[r.nextInt(filename.length)];
            if (MyService.mp.isPlaying()) {

            }
            else {

                new PlayShuffleMode().execute(fn);

        }


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

And here is the AsyncTask method:

private class PlayShuffleMode extends AsyncTask<String, Void, Void> {

    @Override
    protected Void doInBackground(String... fn) {

        mService.playfav(fn[0]);
        return null;
    }
}

Solution

  • The problem is your while loop. The while loop will loop continuously on the main thread until you toggle the button, but since the while loop is on the main thread, your UI will get locked up. So you must figure out a way to move the while loop into your AsyncTask.

    One suggestion: Instead of having the AsyncTask inside of the while loop, why not do the inverse and have the while loop in the AsycTask? Something like...

    private playShuffle;
    
    public void onToggleClicked(View view) {
      ToggleButton tb = ((ToggleButton) view);
      tb.setChecked(!tb.isChecked()); // Toggle the state.
    
      if(tb.isChecked()) {
        playShuffle = new PlayShuffleMode();
        playShuffle.execute();
      }
      else {
        playShuffle.cancel();
      }
    }