Обработчик и поток внутри службы продолжают работать, в то время как служба, похоже, остановилась

У меня есть Service, который использует Handler и Thread для запуска некоторого кода каждые 5 секунд. Когда я звоню stopSelf(), служба кажется остановленной, потому что в разделе «Настройки устройства» -> «Приложения» -> «Выполняется» она там не отображается. Но код внутри потока продолжает работать каждые 5 секунд, хотя я остановил службу.
Почему Handler и Thread живы, даже когда служба остановлена? Как остановить Handler и Thread, когда служба остановлена.

final Handler h = new Handler();
final int delay = 5000; // milliseconds

h.postDelayed(new Runnable() {
        public void run() {
            // do something
            final SharedPreferences sharedPref = getSharedPreferences(
                    getString(R.string.prefs), Context.MODE_PRIVATE);
            if (sharedPref != null) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // SOME CODE
                        Log.d("UPDATING"," something here");
                        isUpdated = updateToServer(data);
                        if(isUpdated) {
                            sharedPref.edit().putBoolean("updated",true).commit();
                            stopSelf();
                        }
                    }
                }).start();
            }
            h.postDelayed(this, delay);
        }
    }, delay);

person Mohammed Ali    schedule 11.02.2015    source источник
comment
в onDestroy вы можете вызвать обработчик.removeCallBacks(runnable)   -  person Ramesh    schedule 11.02.2015


Ответы (3)


Вы должны проверить isUpdated перед публикацией Runnable, если isUpdated==true, не публиковать снова, используйте следующий код:

final Handler h = new Handler();
final int delay = 5000; // milliseconds

h.postDelayed(new Runnable() {
        public void run() {
            // do something
            final SharedPreferences sharedPref = getSharedPreferences(
                    getString(R.string.prefs), Context.MODE_PRIVATE);
            if (sharedPref != null) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // SOME CODE
                        Log.d("UPDATING"," something here");
                        isUpdated = updateToServer(data);
                        if(isUpdated) {
                            sharedPref.edit().putBoolean("updated",true).commit();
                            stopSelf();
                        }
                    }
                }).start();
            }
            if(!isUpdated){
               h.postDelayed(this, delay);
            }

        }
    }, delay);
person Lei Guo    schedule 11.02.2015

Как следует из названия, поток запускается отдельно от службы, поэтому он не остановится, просто остановив службу. На самом деле я не тестировал этот код, но он должен остановить ваш поток и обработчик или дать вам общее представление о том, как это сделать.

final Handler h = new Handler();
final int delay = 5000; // milliseconds
private boolean isRunning = true;  // a variable to signal stopping the thread

h.postDelayed(new Runnable() {
    public void run() {
        // do something
        final SharedPreferences sharedPref = getSharedPreferences(
                getString(R.string.prefs), Context.MODE_PRIVATE);
        if (sharedPref != null) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                  if (isRunning) {
                    // SOME CODE
                    Log.d("UPDATING"," something here");
                    isUpdated = updateToServer(data);
                    if(isUpdated) {
                        sharedPref.edit().putBoolean("updated",true).commit();
                        isRunning = false;  // used to stop the thread from continuing the work
                        h.removeCallbacks(this);  // stopping handler ("this" is the handler runnable you are stopping)
                        stopSelf();
                    }
                  }
                }
            }).start();
        }
        h.postDelayed(this, delay);
    }
}, delay);

Надеюсь, это поможет вам...

person miselking    schedule 11.02.2015
comment
Я не пробовал этот способ, но похоже, что это тоже может сработать. - person Mohammed Ali; 12.02.2015

Я думаю, вам нужно позвонить myHandler.getLooper().quit(), прежде чем останавливать службу.

person Ze Luis    schedule 11.02.2015
comment
Вы имеете в виду, что я звоню h.getLooper().quit() непосредственно перед звонком stopSelf()? - person Mohammed Ali; 11.02.2015
comment
@МохаммедАли Абсолютно. - person Ze Luis; 11.02.2015
comment
Это вызывает сбой! Ошибка: java.lang.RuntimeException: Main thread not allowed to quit. - person Mohammed Ali; 11.02.2015
comment
Вместо этого проверьте это: Looper mLooper = Looper.myLooper(); if (mLooper!=null) { mLooper.quit(); } - person Ze Luis; 11.02.2015
comment
Извините, я не могу много экспериментировать. Я не думаю, что это сработает здесь. - person Mohammed Ali; 11.02.2015
comment
Пробовал, не решает мою проблему, Looper.myLooper() давал ноль. - person Mohammed Ali; 11.02.2015