Android Runnable работает быстрее после возобновления

Сценарий

У меня есть runnable, который выводит значение переменной каждые 1 секунду. Runnable запускается, когда я запускаю mainActivity, и запускается во всем приложении в фоновом режиме.

Проблема

Когда я закрываю приложение (скрытое состояние) и снова запускаю приложение, logcat начинает выводить быстрее. Каждый раз, когда я это делаю, все идет быстрее. Почему ?

@Override
public void onStart()
{
    mHandler.postDelayed(myRunnable, 1000);
    super.onStart();
}

 public Runnable myRunnable = new Runnable()
 {
    @Override
    public void run()
    { 
       count ++;
       android.util.Log.w("     SYNC     ", "COUNT:"+count);
       mHandler.postDelayed(myRunnable, 1000);
    }
};

РЕШЕНИЕ / РЕДАКТИРОВАНИЕ

Спасибо всем за ответ! Я отдаю должное. Однако это был @pskink, который опубликовал этот Android Runnable быстрее работает после возобновления работы, это решило это для меня.


person Janpan    schedule 15.01.2014    source источник
comment
Чем занимается ваш onResume?   -  person Scary Wombat    schedule 15.01.2014
comment
На данный момент ничего. Сначала у меня был код onStart в onResume, и я поменял его местами, чтобы увидеть, есть ли разница.   -  person Janpan    schedule 15.01.2014
comment
потому что ты начинаешь это снова и снова   -  person pskink    schedule 15.01.2014
comment
@pskink Даже если я поставлю этот код mHandler.postDelayed (myRunnable, 1000); в методе onCreate он делает то же самое.   -  person Janpan    schedule 15.01.2014
comment
@BrianRoach, я тоже пробовал, удалив его из onStart, и он делает то же самое.   -  person Janpan    schedule 15.01.2014
comment
@Janpan, поэтому вызовите removeCallbacksAndMessages (null) в onCreate   -  person pskink    schedule 15.01.2014
comment
@pskink Это неплохо работает. Спасибо ! Ответь.   -  person Janpan    schedule 15.01.2014


Ответы (5)


вызовите removeCallbacksAndMessages (null) перед вызовом postDelayed

person pskink    schedule 15.01.2014
comment
Спасибо, отлично работает. Я добавил removeCallbacksAndMessages (null) в onCreate, а затем добавил это в onResume, mHandler.removeCallbacks (myRunnable); mHandler.postDelayed (myRunnable, 1000); , и он работает так, как должен. - person Janpan; 15.01.2014

Поскольку каждый раз, когда вы показываете приложение после скрытия, вызывается метод onStart, в результате чего создается новый экземпляр runnable, выполняющий ту же работу.

Итак, чтобы решить эту проблему, вам нужно остановить метод Runnable in onStop.

Как правило, при переопределении методов жизненного цикла, таких как onCreate , onStart, onResume для запуска некоторого непрерывного поведения, вам необходимо отключить это поведение в их соответствующих аналогах (onDestroy, onStop, onPause).

Итак, в вашем случае один из способов отключить поведение, запускаемое в onStart (запуск нового потока), - это остановить этот поток в onStop. Например:

public Runnable myRunnable = new Runnable()
 {
    private boolean stopped = false;
    public synchronized void stop() {
       stopped = true;             
    }
    public synchronized void reset() {
       stopped = false;             
    }
    @Override
    public void run()
    { 
       if(stopped) return;
       count ++;
       android.util.Log.w("     SYNC     ", "COUNT:"+count);
       mHandler.postDelayed(myRunnable, 1000);
    }
};

Теперь просто вызовите myRunnable.stop() в onStop() методе. Если вы повторно используете экземпляр myRunnable, вызовите myRunnable.reset() в onStart(), чтобы снова включить его.

person hendrix    schedule 15.01.2014
comment
Даже если я поставлю этот код mHandler.postDelayed (myRunnable, 1000); в методе onCreate он делает то же самое. - person Janpan; 15.01.2014
comment
если вы используете onCreate для запуска поведения, отключите это поведение в onDestroy, если вы используете onStart, вы должны использовать onStop для отключения поведения. - person hendrix; 15.01.2014

Может этот образ поможет. Если вы переместите свой код в onCreate, все должно быть в порядке.

введите описание изображения здесь

person Scary Wombat    schedule 15.01.2014

Вы можете спросить, есть ли у вас уже запущенный в onStart (). I, если он равен нулю, вы создаете новый исполняемый объект, а если он не равен нулю, вы ничего не делаете

person Isaac Obradors    schedule 15.01.2014
comment
Но в этом случае указатель на runnable, как и счетчик, должен быть статическим. - person 18446744073709551615; 15.01.2014

пытаться

removeCallbacks(myRunnable)

в onPause () и опубликуйте обратные вызовы в onResume ()

ИЗМЕНИТЬ (включая мои комментарии в ответ):

Когда вы вернетесь к Activity, Activity фактически воссоздается, поэтому у вас есть два Activity: одно показанное и одно невидимое. И runnables по-прежнему репостят себя, каждый из которых имеет неявный указатель на Activity, который его создал ... Обычно это называется утечкой или утечкой активности.

Также обратите внимание, что код, который выполняется без взаимодействия с пользователем, не следует помещать в Activity, это должен быть Service.

Кроме того, если счетчик не статичен, вы не сможете получить к нему доступ после того, как ваше действие покинет экран.

С точки зрения MVC (Модель - Представление - Контроллер) Activity = Контроллер. Представление - это иерархия представлений, указанная в XML макета, мы можем создавать наши собственные настраиваемые классы представлений, но обычно мы повторно используем существующие. И Модель - это то, что должно выжить после поворота экрана на 90 градусов (Activity и иерархия представления воссоздаются заново при изменении ориентации). Выполнимая логика повторной публикации, скорее всего, должна принадлежать модели.

person 18446744073709551615    schedule 15.01.2014
comment
Это заставляет runnable останавливаться, когда я выхожу из действия. Однако это не то, что я хочу. - person Janpan; 15.01.2014
comment
Когда вы вернетесь к Activity, Activity фактически воссоздается, поэтому у вас есть два Activity: одно показанное и одно невидимое. И runnables по-прежнему репостят себя, каждый из которых имеет неявный указатель на Activity, который его создал ... Обычно это называется утечкой или утечкой активности. - person 18446744073709551615; 15.01.2014
comment
Также обратите внимание, что код, который выполняется без взаимодействия с пользователем, не следует помещать в Activity, это должен быть Service. - person 18446744073709551615; 15.01.2014
comment
Кроме того, если counter не является статическим, вы не сможете получить к нему доступ после того, как ваше действие покинет экран. - person 18446744073709551615; 15.01.2014
comment
Спасибо за ваш вклад. Я кое-что узнал, хотя уже несколько лет занимаюсь разработкой для Android. Это улучшило мое понимание жизненного цикла деятельности. - person Janpan; 15.01.2014