【问题标题】:Cancle AsyncTask when onBackPressedonBackPressed 时取消 AsyncTask
【发布时间】:2018-01-08 17:59:13
【问题描述】:

点击返回Button时,我正在尝试取消我的AsyncTask,使用此代码:

 @Override
    public void onBackPressed() {
        super.onBackPressed();
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        if(playerTask!=null && !playerTask.isCancelled()) playerTask.cancel(true);
        this.finish();
    }

但不起作用 playerTask 仍然有效:

  PlayerTask playerTask = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pop_for_ringtone);
        mediaPlayer = new MediaPlayer();
        playerTask = new PlayerTask();
        playerTask.execute(url);

/***/

 @SuppressLint("StaticFieldLeak")
    public class PlayerTask extends AsyncTask<String, Void, Boolean> {
        ProgressBar pb = findViewById(R.id.progress);

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
                mediaPlayer.setAudioAttributes(attribs);

            } else {
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            }
        }

        @Override
        protected Boolean doInBackground(String... strings) {
            if(!isCancelled()) {
            try {
                mediaPlayer.setDataSource(strings[0]);
                mediaPlayer.prepare();
                prepared = true;
            } catch (IOException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mediaPlayer) {
                    mediaPlayer.start();
                }
            });

        }
        else
        {
            playerTask.cancel(true);
        }
        return prepared;

        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            music.setEnabled(true);
            music.setVisibility(View.VISIBLE);
            music.setChecked(true);
        }
    }

【问题讨论】:

  • 只需选择 RX-Java Observable 模式。这是一个比异步任务更好的解决方案。

标签: java android android-asynctask


【解决方案1】:

试试这个

@Override
public void onBackPressed() {
    // if playerTask == null mediaPlayer is never start, no need to handle

    if(playerTask != null && playerTask.getStatus() == AsyncTask.Status.FINISHED) {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
    } else if (playerTask != null && playerTask.getStatus() != AsyncTask.Status.FINISHED) {
        // It mean your task is running, should stop your mediaPlayer inside your task
        playerTask.cancel(true);
    }
   super.onBackPressed();
}

并且在您的 PlayerTask 中覆盖 onCancelled 方法

@Override
protected void onCancelled(Boolean aBoolean) {
    if(isCancelled() && mediaPlayer.isPlaying()) {
         mediaPlayer.stop();
    }
}

希望对你有帮助

【讨论】:

    【解决方案2】:

    你有 2 个问题需要改变。

    1.当你在取消playerTask之前调用super.onBackPressed();,你的activity会首先销毁。所以你应该在playerTask取消之后调用。

    2.当判断playTask正在运行时,还需要使用playerTask.getStatus() == AsyncTask.Status.RUNNING

    改变

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        if(playerTask!=null && !playerTask.isCancelled()) playerTask.cancel(true);
        this.finish();
    }
    

    @Override
    public void onBackPressed() {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        if(playerTask!=null && !playerTask.isCancelled() && playerTask.getStatus() == AsyncTask.Status.RUNNING){
            playerTask.cancel(true);
            playerTask = null;
        }
        super.onBackPressed();
        this.finish();
    }
    

    【讨论】:

    • 非常感谢您的回答,但当我单击返回按钮时仍然无法使用 Playertask 仍然可以使用
    【解决方案3】:

    参考AsyncTask.cancel(boolean)AsyncTask cancel(boolean) 的文档,我们看到此方法仅将isCancelled() 设置为提供true,并导致执行onCancelled() 函数而不是onPostExecute()。因此,如果您需要正确取消 AsyncTask,您需要添加一个标志以定期检查 doInBackground() 中的 if(!isCancelled()) 并停止执行。你的代码看起来像这样

    @Override
            protected Boolean doInBackground(String... strings) {
    
                if(!isCancelled()){
                //ToDo:whatever you need to do in the asynctask
                }
                else{
                //ToDo: cancel the execution
                }
                }
    
            }
    

      MediaPlayer mediaPlayer = new MediaPlayer();
      if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
        mediaPlayer.setAudioAttributes(attribs);
    
      } else {
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
      }
      mediaPlayer.setDataSource(url);
      mediaPlayer.prepareAsync();
      mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {
          mediaPlayer.start();
          music.setEnabled(true);
          music.setVisibility(View.VISIBLE);
          music.setChecked(true);
        }
      });
    

    然后onBackPressed() 你可以做mediaPlayer.release()

    【讨论】:

    • 你在 doInBackground 方法中做了什么改变?
    • AsyncTask.cancel(true) 不会取消任何内容。只需将取消标志设置为真。您需要使用该标志自行取消执行
    • 不,我不是这个意思。所以player.cancel(true) 什么都不做。您需要做的是停止mediaPlayer.prepare() 的执行。查看此答案以在准备 release mediaPlayer 时释放 mediaPlayer
    • 如果您仍然感到困惑,请告诉我。我会进一步解释
    • 请你解释一下
    【解决方案4】:

    我使用以下代码在媒体播放时创建了 wave, 并在单击后退按钮或停止按钮时停止播放器。

    复制到xml文件中。

    <VisualizerView
                android:id="@+id/waveform_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white"/>
    

    MainActivity.java

    private MediaPlayer myMediaPlayer;      
    private VisualizerView mWaveformView;   
    Visualizer audioOutput = null;
    
    onCreate()
    {
         mWaveformView = (VisualizerView) findViewById(R.id.waveform_view);
         myButtonPlayLastRecordAudio.setOnClickListener(this);
    }
    
      @Override
        public void onClick(View v) {
            switch (v.getId()) {
                  case R.id.buttonPlay:
                    myAudioSavePathInDevice = Environment.getExternalStorageDirectory().toString() + "/" +
                            "AudioRecording.3gp";
    
    
                    myMediaPlayer = new MediaPlayer();
                    myMediaPlayer.setVolume(1.5f, 1.5f);
                    if (myAudioSavePathInDevice == null || myAudioSavePathInDevice.isEmpty()) {
                        Toast.makeText(MainActivity.this, "No Audio Found", Toast.LENGTH_LONG).show();
                    } else {
                        try {
                            FileInputStream is = new FileInputStream(myAudioSavePathInDevice);
                            myMediaPlayer.setDataSource(is.getFD());
    
    
                            myMediaPlayer.prepare();
                            myMediaPlayer.start();
                            Toast.makeText(AudioRecordingActivity.this, "Recording Playing", Toast.LENGTH_LONG).show();
    
                            mWaveformView.clear();
                            createVisualizer();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
    
                        myMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                            @Override
                            public void onCompletion(MediaPlayer mp) {
                                audioOutput.setEnabled(false);
                            }
                        });
                    }
    
                    break;
    
                case R.id.buttonStopAudio:
                    mediaPlayerReleaseResources();
    
                    break;
    
            }
    }
    
    
    
     private void createVisualizer() {
            int rate = Visualizer.getMaxCaptureRate();
            audioOutput = new Visualizer(myMediaPlayer.getAudioSessionId()); // get output audio stream
    
            audioOutput.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
                @Override
                public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
                    int max = 0, min = 255;
                    for (int i = 0; i < waveform.length; i++) {
                        int w = (int) waveform[i] & 0xFF;
                        max = Math.max(w, max);
                        min = Math.min(w, min);
                    }
                    mWaveformView.addAmplitude((max - min)); // update the VisualizeView
                    mWaveformView.invalidate(); // refresh the VisualizerView
                }
    
                @Override
                public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
    
                }
            }, rate, true, false); // waveform not freq data
            audioOutput.setEnabled(true);
        }
    
    
         private void mediaPlayerReleaseResources() {
            if(myMediaPlayer != null) {
                if (myMediaPlayer.isPlaying()) {
                    myMediaPlayer.stop();
                }
            }
            if( audioOutput != null)
                audioOutput.setEnabled(false);
        }
    
    
         @Override
        public void onBackPressed() {
            super.onBackPressed();
            mediaPlayerReleaseResources();
        }
    

    VisualizerView.class

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.View;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class VisualizerView extends View {
        private static final int LINE_WIDTH = 3; // width of visualizer lines
        private static final int LINE_SCALE = 4; // scales visualizer lines
        private List<Float> amplitudes; // amplitudes for line lengths
        private int width; // width of this View
        private int height; // height of this View
        private Paint linePaint; // specifies line drawing characteristics
    
        private float temp_scale = 3;
        float heighest = temp_scale;
    
        // constructor
        public VisualizerView(Context context, AttributeSet attrs) {
            super(context, attrs); // call superclass constructor
            linePaint = new Paint(); // create Paint for lines
            linePaint.setColor(Color.BLACK); // set color to green
            linePaint.setStrokeWidth(LINE_WIDTH); // set stroke width
        }
    
        // called when the dimensions of the View change
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            width = w; // new width of this View
            height = h; // new height of this View
            amplitudes = new ArrayList<Float>(width / LINE_WIDTH);
    
        }
    
        // clear all amplitudes to prepare for a new visualization
        public void clear() {
            heighest = 3;
            amplitudes.clear();
        }
    
        // add the given amplitude to the amplitudes ArrayList
        public void addAmplitude(float amplitude) {
            amplitudes.add(amplitude); // add newest to the amplitudes ArrayList
    
            // if the power lines completely fill the VisualizerView
            if (amplitudes.size() * LINE_WIDTH >= width) {
                amplitudes.remove(0); // remove oldest power value
            }
        }
    
        // draw the visualizer with scaled lines representing the amplitudes
        @Override
        public void onDraw(Canvas canvas) {
            int middle = height / 2; // get the middle of the View
            float curX = 0; // start curX at zero
    
            // for each item in the amplitudes ArrayList
            for (float power : amplitudes) {
                heighest = Math.max(power, heighest);
                temp_scale = heighest / height;
    
                float scaledHeight = power / temp_scale; // LINE_SCALE; // scale the power
                curX += (LINE_WIDTH); // increase X by LINE_WIDTH
                // draw a line representing this item in the amplitudes ArrayList
                canvas.drawLine(curX, middle + scaledHeight / 2, curX, middle
                        - scaledHeight / 2, linePaint);
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多