一个计时器对象,更新了TextView中的所有计时器

如何解决一个计时器对象,更新了TextView中的所有计时器

我的应用程序应显示多个计时器并同时启动它们。

问题在于这些程序无法同步运行。您可以在GIF上看到这一点,可以看到它们失去了同步性。 一定时间后,您会看到计时器的更新速度比其他计时器快。显示第一个计时器1,然后显示延迟的计时器2,然后显示特定的延迟计时器3。

我想创建多个计时器,每个计时器都有不同的持续时间。 我想在TextView中显示这些计时器。我在%{DOCUMENT_ROOT}/.well-known/acme-challenge/的ArrayList中初始化它。然后将它们添加到MainActivity中,以便也显示它们。首先,我将经历一个for循环并为每个单独的对象执行ReyclerView方法。不幸的是,每个定时器的时间都不正确。这意味着一个计时器更快,第二个计时器更慢,依此类推。因此,每个计时器都在不同的时间启动,或者文本在不同的时间更改。

一个广告中仅包含一个计时项(例如ScheduledExecutorService) viewmodel,而不是活动中的10。虽然您可能想描绘10 时间,在用户界面中,您只需要一个计时项即可告诉您何时 秒已过去。让viewmodel发出时间值的详细信息 应该在用户界面中呈现的让用户界面仅显示那些 时间值

上面的文本是一个答案。我该如何构建它以便只有一个计时器元素并控制时间?如何让这些计时器同步运行? 每个计时器应同时更新并显示。 我期待着一个答案,在此先感谢您的支持!

enter image description here

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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-