Android - периодически запускает метод, используя вызов postDelayed()

У меня есть ситуация в приложении для Android, где я хочу начать сетевую активность (отправка некоторых данных), которая должна запускаться каждую секунду. Я достигаю этого следующим образом:

В onCreate() у меня есть код:

tv = new TextView(this);
tv.postDelayed(sendData, 1000);

Функция sendData():

   Handler handler = new Handler();
   private Runnable sendData=new Runnable(){
    public void run(){
        try {
            //prepare and send the data here..
            handler.removeCallbacks(sendData);
            handler.postDelayed(sendData, 1000);    
        }
        catch (Exception e) {
            e.printStackTrace();
        }   
    }
};

Проблема возникает следующим образом: Когда пользователь нажимает кнопки назад и приложение выходит (пользовательский интерфейс исчезает), функция sendData() все еще выполняется, и это то, что я хочу. Теперь, когда пользователь перезапускает приложение, мой onCreate() снова вызывается, и я получаю sendData(), вызывается два раза в секунду. Так и происходит. Каждый раз, когда пользователь выходит и запускается снова, происходит еще одна sendData() в секунду.

Что я делаю неправильно? Это моя проблема с new Handler()? Каков наилучший способ справиться с этим? Я хочу один вызов sendData() в секунду, пока пользователь не покинет приложение (менеджер приложений формы).

Ответ 1

Почему вы не создаете сервис и не ставите логику в onCreate(). В этом случае, даже если вы нажмете кнопку "Назад", служба продолжит выполнение. и как только вы входите в приложение, он не будет звонить onCreate() снова. Скорее он назовет onStart()

Ответ 2

final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
      @Override
      public void run() {
        //Do something after 100ms
        Toast.makeText(c, "check", Toast.LENGTH_SHORT).show();  
        handler.postDelayed(this, 2000);
      }
    }, 1500);

Ответ 3

Возможно, для достижения этого требуются методы жизненного цикла активности:

Handler handler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      handler.post(sendData);
}

@Override
protected void onDestroy() {
      super.onDestroy();
      handler.removeCallbacks(sendData);
}


private final Runnable sendData = new Runnable(){
    public void run(){
        try {
            //prepare and send the data here..


            handler.postDelayed(this, 1000);    
        }
        catch (Exception e) {
            e.printStackTrace();
        }   
    }
};

В этом подходе, если вы нажмете клавишу "назад" в своей деятельности или вызовите finish();, она также остановит вызовы postDelayed.

Ответ 4

Вы можете упростить код следующим образом.

В Java:

new Handler().postDelayed (() -> {
    //your code here
}, 1000);

В Котлине:

Handler().postDelayed({
   //your code here
}, 1000)

Ответ 5

Пожалуйста, проверьте ниже, что он работает на моей стороне в нижнем коде, ваш обработчик будет запускаться через каждые 1 секунду, когда вы находитесь на той же самой активности.

 HandlerThread handlerThread = new HandlerThread("HandlerThread");
                handlerThread.start();
                handler = new Handler(handlerThread.getLooper());
                runnable = new Runnable()
                {
                    @Override
                    public void run()
                    {

                            handler.postDelayed(this, 1000);
                        }
                };
                handler.postDelayed(runnable, 1000);

Ответ 6

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (msg.what==0){
            // do stuff
            h.removeMessages(0);  // clear the handler for those messages with what = 0
            h.sendEmptyMessageDelayed(0, 2000); 
        }
    }
};


 h.sendEmptyMessage(0);  

Ответ 7

Я думаю, вы могли бы экспериментировать с разными флагами активности, поскольку это звучит как несколько экземпляров.

"SingleTop" "SingleTask" "SingleInstance"

Я бы попробовал те, которые могут быть определены внутри манифеста.

http://developer.android.com/guide/topics/manifest/activity-element.html

Ответ 8

Вы должны установить andrid: allowRetainTaskState = "true" для запуска Activity в Manifest.xml. Если эта активация не запускает активность. вы должны установить андроид: launchMode = "singleTask" в этом действии