0

I decided to ease the update time algorithm. Everywhere write an algorithm through the Timer. But if you implement Runnable the interface in the main activity, you can avoid creating an extra object.

I want it when I open the activation, the time was updated every second. But this does not happen. By the tag (ITTERATION) that I created, there is only one iteration. Using an example from HERE

Screenshot of phone preview and logs

I already broke my brain. Help me please :(

package pac.twoproject;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Main2Activity extends AppCompatActivity implements Runnable {

    private static final String TAG = "ITTERATION";
    TextView tv;
    String time;

    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        tv = (TextView) findViewById(R.id.textView);
        //scheduler.scheduleAtFixedRate(this, 0, 10, TimeUnit.MILLISECONDS);
    }

    @Override 
    protected void onResume() {
        super.onResume();

        scheduler.scheduleAtFixedRate(this, 0, 1000, TimeUnit.MILLISECONDS);
    }

    @Override
    public void run() {
        time = sdf.format(new Date(System.currentTimeMillis()));
        tv.setText(time);
        Log.d(TAG, time);
    }
}
WorldSEnder
  • 4,875
  • 2
  • 28
  • 64
magistr4815
  • 640
  • 4
  • 10
  • Related? https://stackoverflow.com/questions/9884246/ Try logging before you make the call to tv.setText. I suspect that an exception is thrown there – WorldSEnder Oct 14 '17 at 17:48
  • I do not get any exception. Or the log is not displayed or time is displayed again. – magistr4815 Oct 14 '17 at 17:58
  • `ScheduledExecutorService` suppresses exceptions. What's more, after one exception, the runnable is unscheduled by default. Wrap your run method body in an try-catch and log it yourself to see if that is what happens. – WorldSEnder Oct 14 '17 at 18:12
  • Я выталкивал каждую секунду. Сделал обертку исключения. Теперь метод Run выглядит так: `try {// мониторим код time = sdf.format (новая дата (System.currentTimeMillis ())); Log.d (TAG, время); tv.setText (время); } catch (RuntimeException e) {Log.d (TAG, "" + e); } Log.d (TAG, "1");` I get an exception 1 time. **"android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."** And how can I fix this? Links do? or how? – magistr4815 Oct 14 '17 at 19:31
  • @worldsender Thank you, you helped me. I unsubscribed in fasting. – magistr4815 Oct 14 '17 at 20:55

3 Answers3

0

You can only modify Views from the main thread (GUI thread) of the application. In your case, when the ScheduledExecutorService calls run, it will do so in a different thread. The result is that tv.setText(time); throws a CalledFromWrongThreadException. The scheduler in turn, seeing that the Runnable threw an exception, will suppress future exections:

Documentation for ScheduledExecutorService

If any execution of the task encounters an exception, subsequent executions are suppressed

There is one, seemingly contradicting, thing left to explain: It works once. This is because your initial delay is 0. This, in turn, means that the first execution might be run synchronously when calling ScheduledExecutorService#scheduleAtFixedRate.


To fix this problem, you have to call tv.setText(time) from your main thread. How to do so, can be found in this question.

WorldSEnder
  • 4,875
  • 2
  • 28
  • 64
0

The administrator helped @WorldSEnder! Thank you! There was an exception "android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views". A new thread called by the function scheduleAtFixedRate could not update the text in the text field. Solved the problem through Handler.

It was easier and more optimized to do it through Timer. Or do you have any idea how to optimize it?

package pac.twoproject;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


public class Main2Activity extends AppCompatActivity implements Runnable {

    private static final String TAG = "ITTERATION";
    TextView tv;
    String time;
    Handler h;

    final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        tv = (TextView) findViewById(R.id.textView);

        h = new Handler() { //создаем наш хендл, в котором пропишем получение из очереди сообщения и обновление нашей переменной
            public void handleMessage(Message msg) {
                Bundle bundle = msg.getData(); // достаем их сообщение наш бондаж
                String text = bundle.getString("key"); // из бондажа уже наше сообщение
                tv.setText(text);
            }
        };

        scheduler.scheduleAtFixedRate(this, 0, 1000, TimeUnit.MILLISECONDS); // функция которая запускает метод ран в новом потоке и повторяем его запуск каждую секунду
    }


    @Override
    public void run() {

        try { // мониторим код
            time = sdf.format(new Date(System.currentTimeMillis())); // считываем время
            Log.d(TAG, time); // пишем его лог

            Message msg = Message.obtain(); // создаем новое сообщение
            Bundle bundle = new Bundle(); // создаем новый сверток (бандаж)
            bundle.putString("key", time); // в него пихаем по ключу наше время (текст)
            msg.setData(bundle); // и уже бондаж запихиваем в сообщение
            h.sendMessage(msg); //отправляем сообщение
        } catch (RuntimeException e) {
            Log.d(TAG, ""+ e);
        }
        Log.d(TAG, "1");
    }
}
magistr4815
  • 640
  • 4
  • 10
-1

I am not applied to android BUT ... run() is processing as it is...
only once except if you use:

while (true) {
    time = sdf.format(new Date(System.currentTimeMillis()));
    tv.setText(time);
    Log.d(TAG, time);
}
UltimateDevil
  • 2,807
  • 2
  • 18
  • 31
  • This answer is wrong. `ScheduledExecutorService#scheduleAtFixedRate` is supposed to take care of repeated execution – WorldSEnder Oct 14 '17 at 18:38
  • I have a function (scheduleAtFixedRate) that makes the Run method every second. What for to me a cycle which will do it constantly. – magistr4815 Oct 14 '17 at 18:43