如何解决一个计时器对象,更新了TextView中的所有计时器
我的应用程序应显示多个计时器并同时启动它们。
问题在于这些程序无法同步运行。您可以在GIF上看到这一点,可以看到它们失去了同步性。 一定时间后,您会看到计时器的更新速度比其他计时器快。显示第一个计时器1,然后显示延迟的计时器2,然后显示特定的延迟计时器3。
我想创建多个计时器,每个计时器都有不同的持续时间。
我想在TextView中显示这些计时器。我在%{DOCUMENT_ROOT}/.well-known/acme-challenge/
的ArrayList中初始化它。然后将它们添加到MainActivity
中,以便也显示它们。首先,我将经历一个for循环并为每个单独的对象执行ReyclerView
方法。不幸的是,每个定时器的时间都不正确。这意味着一个计时器更快,第二个计时器更慢,依此类推。因此,每个计时器都在不同的时间启动,或者文本在不同的时间更改。
一个广告中仅包含一个计时项(例如ScheduledExecutorService) viewmodel,而不是活动中的10。虽然您可能想描绘10 时间,在用户界面中,您只需要一个计时项即可告诉您何时 秒已过去。让viewmodel发出时间值的详细信息 应该在用户界面中呈现的让用户界面仅显示那些 时间值
上面的文本是一个答案。我该如何构建它以便只有一个计时器元素并控制时间?如何让这些计时器同步运行? 每个计时器应同时更新并显示。 我期待着一个答案,在此先感谢您的支持!
MainActivity
startTimer()
ModelTimer
public class MainActivity extends AppCompatActivity implements ModelTimer.MyCallback {
private RecyclerView recyclerView;
private Button button_start;
private Dialog epicDialog;
public static ArrayList<ModelTimer> timerList;
public static TimerAdapter adapter;
public static Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
recyclerView = findViewById(R.id.recyclerview_timers);
button_start = findViewById(R.id.button_start);
timerList= new ArrayList<>();
for (int i = 1; i <= 10; i++) {
timerList.add(new Timer(i,600000 * i))); //Each timer has a different time
}
recyclerView.setLayoutManager(recyclerViewLayoutManager);
adapter = new TimerAdapter(this,timerList);
recyclerView.setAdapter(adapter);
context = this;
button_start.setOnClickListener(v -> {
for (Timer timer: timerList) {
timer.startTimer();
});
@Override
public void updateMyText(int index,long time) {
timerList.get(index-1).setTime(time);
adapter.notifyDataSetChanged();
}
}
@Override
public void updateMyText(int index,long time) {
timerList.get(index-1).setTime(time);
adapter.notifyDataSetChanged();
}
}
TimerAdapter
public class ModelTimer {
public interface MyCallback {
public void updateMyText(int index,long time);
}
private int index;
private long time;
private CountDownTimer mCountDownTimer;
private boolean mTimerRunning;
private long startTime;
private long mTimeLeftInMillis;
private String timeLeftFormatted;
private MyCallback myCallback = null;
public ModelTimer(int index,long startTimeMilliseconds,MyCallback callback) {
this.index = index;
this.time = startTimeMilliseconds;
mTimeLeftInMillis = startTimeMilliseconds;
startTime = startTimeMilliseconds;
this.myCallback = callback;
}
public void startTimer() {
mCountDownTimer = new CountDownTimer(mTimeLeftInMillis,1000) {
@Override
public void onTick(long millisUntilFinished) {
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
}
@Override
public void onFinish() {
mTimerRunning = false;
}
}.start();
mTimerRunning = true;
}
public void resetTimer() {
mCountDownTimer.cancel();
mTimerRunning = false;
mTimeLeftInMillis = startTime;
timeLeftFormatted = formattedTime(startTime);
changeText(index-1);
}
public void updateCountDownText() {
//System.out.println("ID: " + getIndex() + " " + mTimeLeftInMillis);
if(myCallback != null) {
myCallback.updateMyText(getIndex(),mTimeLeftInMillis);
}
}
private void changeText(int element) {
String[] data = timeLeftFormatted.split(":");
int hours = Integer.parseInt(data[0]);
int minutes = Integer.parseInt(data[1]);
int seconds = Integer.parseInt(data[2]);
int timeSeconds = seconds + 60 * minutes + 3600 * hours;
long milliseconds = TimeUnit.MILLISECONDS.convert(timeSeconds,TimeUnit.SECONDS);
MainActivity.countdownList.get(element).setTime(milliseconds);
MainActivity.adapter.notifyDataSetChanged();
}
public static long getMilliseconds(String time) {
String[] data = time.split(":");
int hours = Integer.parseInt(data[0]);
int minutes = Integer.parseInt(data[1]);
int seconds = Integer.parseInt(data[2]);
int timeSeconds = seconds + 60 * minutes + 3600 * hours;
return TimeUnit.MILLISECONDS.convert(timeSeconds,TimeUnit.SECONDS);
}
public static String formattedTime(long time) {
int milliToSec = (int) (time / 1000);
int hours = milliToSec / 3600;
int minutes = (milliToSec / 60) % 60;
int seconds = milliToSec % 60;
return String.format(Locale.getDefault(),"%02d:%02d:%02d",hours,minutes,seconds);
}
public int getIndex() {
return this.index;
}
public void setIndex(int index) {
this.index = index;
}
public long getTime() { return this.time; }
public void setTime(long time) {
this.time = time;
}
}
解决方法
如果需要,可以使用CountDownTimer进行尝试。看起来像这样:
public class TimerHelper {
public interface UpdateCallback {
/**
* @return true if want to be updated again false otherwise
*/
boolean secondPassedCallback();
}
private ArrayList<UpdateCallback> callbacksList = new ArrayList<>();
/**
* @param maxTime maximum of all timers
*/
public void start(int maxTime) {
CountDownTimer mCountDownTimer = new CountDownTimer(maxTime,1000) {
@Override
public void onTick(long millisUntilFinished) {
ArrayList<UpdateCallback> itemsToRemove=new ArrayList<>();
for (UpdateCallback updateCallback : callbacksList) {
boolean wantToBeUpdated = updateCallback.secondPassedCallback(); // remove timers that reached 0
if (!wantToBeUpdated) {
itemsToRemove.add(updateCallback);
}
}
callbacksList.removeAll(itemsToRemove);
}
@Override
public void onFinish() {
}
};
mCountDownTimer.start();
}
public boolean addCallback(UpdateCallback callback) {
return callbacksList.add(callback);
}
public boolean removeCallback(UpdateCallback callback) {
return callbacksList.remove(callback);
}
}
有了这个,只需让您的ModelTimer实现此回调并在那里进行UI更新即可。最后,在活动中将button_start OnClickListener更改为:
button_start.setOnClickListener(v -> {
TimerHelper t = new TimerHelper();
for (ModelTimer timer : timerList) {
t.addCallback(timer);
}
});
,
您可以在ReyclerView ViewHolder
中而不是在ModelTimer
中
chronometer.setBase(new Date().getTime());
chronometer.setOnChronometerTickListener(new OnChronometerTickListener() {
public void onChronometerTick(Chronometer cArg) {
long t = SystemClock.elapsedRealtime() - cArg.getBase();
cArg.setText(DateFormat.format("HH:mm:ss",t));
}
});
chronometer.start();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。