Good day to all. It is necessary that every minute the title of my ActionBar in the Activity changed. There should be a time format mm:ss . Naturally, I will not engage in such a process in the main thread, and I created a separate one. But this team

 getSupportActionBar().setTitle(new SimpleDateFormat("mm:ss").format(new Date(this.time))); 

requires me to run it in the main thread, and not in any other one, since Exception crashes. Rummaged on the Internet, where I was told that you can do this way

 runOnUiThread(new Runnable() { @Override public void run() { getSupportActionBar().setTitle(new SimpleDateFormat("mm:ss").format(new Date(this.time))); } }); 

But, unfortunately, this option is not very good. By the fortieth minute, my application flew out for an unknown reason. Understood in the logs, and found that it took too many milliseconds to run the runOnUiThread , after which this command was simultaneously launched twice. I noticed that my title is changing unevenly. After all, it should be updated after 1000 ms, which means a second, but it is updated then 900 ms, then 1200 ms and so on. What is the reason I do not know. How to solve the problem so that the header changes exactly every 1000 ms?

I will ask you not to suggest me simply not to use the title, but to create some of my own, for example, TextView in Activity . Also, a bad option is getSupportActionBar().setCustomView(...) , as described here .

    3 answers 3

    What about a handler that allows you to execute deferred code? Here is an example:

     private final int ONE_SECOND = 1000; private Handler mHandler = new Handler(); private Runnable timeUpdaterRunnable = new Runnable() { @Override public void run() { //тут что нибудь делается }; 

    But the launch of the delayed task:

     mHandler.postDelayed(this, ONE_SECOND); 
    • Where do you have a comment //тут что-нибудь делается you can insert getSupportActionBar().setTitle(...) ? - nick
    • Yes, you can insert. It seems that you do not even need to specify runOnUiThread, but this is not accurate. - Kota1921
    • No, Handler does not fit: Exception: only the original thread that... can touch it views - nick
    • Well, do runOnUiThread, what's the problem? - Kota1921
    • That's the problem - nick

    This article was also helped by the user @ Kota1921, thanks to whom he understood where to dig.

    You need to create a global variable:

     private Handler i6; 

    In the onCreate(...) method, declare this variable:

     this.i6 = new Handler() { @SuppressWarnings("deprecation") @Override public void handleMessage(Message i1) { getSupportActionBar().setTitle(Html.fromHtml("<i>" + Game.this.i2[0].getProperty("style_textColor") + "\">" + i1.obj + "</i>")); } }; 

    And from here:

     new Thread(new Runnable() { private Long i1 = 0L; @Override public void run() { while (true) { ... Thread.sleep(1000L); this.i1 += 1000L; Message i2 = new Message(); i2.obj = new SimpleDateFormat("mm:ss").format(new Date(this.i1)); MyActivity.this.i6.sendMessage(i2); } } }).start(); 

      Try running such code in the main thread:

       Thread thread = new Thread("Run update") { public void run(){ try { initServer(); } catch (Exception e1) { System.out.println("Cant create.. "+e1); e1.printStackTrace(); } } }; thread.start(); 

      where initServer:

        private initServer(){ isServerWorking=true; Вместо isServerWorking вставляем любую проверку остановки нашего обновления(приложение закрыто системой, пользователь закрыл программу и т.д.) while (isServerWorking){ В методе update() прописываем всю нужную нам логику update(); try { Задержка небольшая, чтобы бесконечно не обновлялось, иначе процесс будет уж очень много кушать Thread.sleep(MILLSECUPDATE); } catch (InterruptedException e) { e.printStackTrace(); } }} 

      I hope the idea is clear.