取消后无法重新创建和安排计时器增益。为什么?
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);
我目前正在学习如何在 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);