取消后无法重新创建和安排计时器增益。为什么?

Can't recreate and schedule Timer gain after cancelling it. Why?

我目前正在学习如何在 Android 上编写应用程序。 这是我的尝试:

    package com.example.android.miwok;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import static android.view.View.GONE;

/**
 * Created by Lukas on 14.02.2018.
 */

public class WordAdapter extends ArrayAdapter<Word> {
    public static Timer timer;
    Activity act;
    MediaPlayer player;

    public WordAdapter(Activity context, ArrayList<Word> list) {
        super(context, 0, list);
        this.act = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View listItemView = convertView;
        if (listItemView == null) {
            listItemView = LayoutInflater.from(getContext()).inflate(R.layout.listitem_normal, parent, false);
        }
        Word current_word = getItem(position);
        final TimerTask progresstask;
        final AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
        LayoutInflater inflater = LayoutInflater.from(getContext());
        View dialogview = inflater.inflate(R.layout.player_dialog, null);
        final ProgressBar progress = dialogview.findViewById(R.id.progress);
        final SeekBar volseek = dialogview.findViewById(R.id.volumeseek);
        TextView MiwokView = listItemView.findViewById(R.id.miwok_word);
        TextView DefaultView = listItemView.findViewById(R.id.default_word);
        final TextView TimeGone = dialogview.findViewById(R.id.time_gone_player);
        final TextView TimeTotal = dialogview.findViewById(R.id.time_total);
        final ImageView icon = listItemView.findViewById(R.id.item_image);
        final ImageButton playbutton = listItemView.findViewById(R.id.playbutton);
        final ImageButton volup = dialogview.findViewById(R.id.vol_up);
        final ImageButton voldown = dialogview.findViewById(R.id.vol_down);
        MiwokView.setText(current_word.getMiwokTranslation());
        DefaultView.setText(current_word.getDefaultTranslation());
        if (current_word.getImageRes() == 0) {
            icon.setVisibility(GONE);
        } else {
            icon.setImageResource(current_word.getImageRes());
        }
        volup.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) + 1, 0);
            }
        });
        voldown.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AudioManager audioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) - 1, 0);
            }
        });

        dialog.setTitle(current_word.getMiwokTranslation());
        dialog.setMessage(current_word.getDefaultTranslation());
        dialog.setView(dialogview);
        progresstask = new TimerTask() {
            @Override
            public void run() {
                act.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        TimeGone.setText(Integer.toString(player.getCurrentPosition()));
                    }
                });
                progress.setProgress(player.getCurrentPosition());
            }
        };
        final AlertDialog crdialog = dialog.create();
        crdialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                player.stop();
                timer.cancel();
                timer.purge();
                timer = null;
                Log.i("Miwok/Timer Task", "Timer cancelled");
                playbutton.setImageResource(android.R.drawable.ic_media_play);
                Log.d("onDismiss", "onDismiss: executed");
            }
        });
        playbutton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                player = MediaPlayer.create(getContext(), R.raw.unison_aperture_ncs_release);
                player.start();
                playbutton.setImageResource(android.R.drawable.ic_media_pause);
                crdialog.show();
                progress.setMax(player.getDuration());
                TimeTotal.setText(Integer.toString(player.getDuration() / 60));
                timer = new Timer();
                timer.scheduleAtFixedRate(progresstask, 0, 500);
                player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mediaPlayer) {
                        crdialog.dismiss();
                        playbutton.setImageResource(android.R.drawable.ic_media_play);
                    }
                });
            }
        });
        return listItemView;

    }
}

如您所见,如果您单击 ImageButton,将显示一个带有进度的对话框,并且将创建 timer 的新实例。 但是我收到这个错误:

04-02 21:47:36.602 27524-27524/com.example.android.miwok E/AndroidRuntime: FATAL EXCEPTION: main
                                                                           Process: com.example.android.miwok, PID: 27524
                                                                           java.lang.IllegalStateException: Task already scheduled or cancelled
                                                                               at java.util.Timer.sched(Timer.java:401)
                                                                               at java.util.Timer.scheduleAtFixedRate(Timer.java:328)
                                                                               at com.example.android.miwok.WordAdapter.onClick(WordAdapter.java:115)
                                                                               at android.view.View.performClick(View.java:6213)
                                                                               at android.view.View$PerformClick.run(View.java:23645)
                                                                               at android.os.Handler.handleCallback(Handler.java:751)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                               at android.os.Looper.loop(Looper.java:154)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)

如果有人能解释为什么会出现此错误以及我该如何解决,我会很高兴。 非常感谢!

简而言之,因为您对多个计时器使用相同的TimerTask

里面Timer class有一张支票:

if (task.state != TimerTask.VIRGIN)
   throw new IllegalStateException("Task already scheduled or cancelled");

因此,如果 TimerTask 已被使用,则不能在另一个计时器中使用它。

换句话说,您必须为新的 Timer 创建新的 TimerTask 或限制自己只使用一对

试试这个:

progresstask.run();

或重新创建给计时器另一个实例,因为您取消了它:

timer = new Timer();
timer.scheduleAtFixedRate(progresstask, 0, 500);