Остановка службы приводит к потере сирот - PullRequest
1 голос
/ 12 июня 2011

Я продолжаю учиться из книги «Pro Android 2», работая на примере Сервиса, который состоит из двух классов: BackgroundService.java и MainActivity.java. Класс MainActivity показан ниже и имеет пару кнопок. Кнопка unbind, unbindBtn, останавливает Службу, но, похоже, больше ничего не делает, например, завершает поток, который Служба запустила.

    public class MainActivity extends Activity {
        private static final String TAG = "MainActivity";

        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            Log.d(TAG, "starting service");

            Button bindBtn = (Button)findViewById(R.id.bindBtn);
            bindBtn.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    Intent backgroundService = new Intent(MainActivity.this, com.marie.mainactivity.BackgroundService.class);
                    startService(backgroundService);
                }
            });

            Button unbindBtn = (Button)findViewById(R.id.unbindBtn);
            unbindBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    stopService(new Intent(MainActivity.this, BackgroundService.class));
                }
            });
        }
    }

Документация гласит: «Если ваша служба будет выполнять какие-либо работы с центральным процессором или блокировать операции…, вы должны создать новый поток в службе для выполнения этой работы». И это именно то, что делает класс BackgroundService ниже. Как вы можете видеть ниже, я добавил цикл while (true) в метод run () потока, чтобы увидеть, что происходит с потоком, когда я останавливаю Службу.

    public class BackgroundService extends Service {
        private NotificationManager notificationMgr;

        @Override
        public void onCreate() {
            super.onCreate();

            notificationMgr = NotificationManager)getSystemService(NOTIFICATION_SERVICE);

            displayNotificationMessage("starting Background Service");

            Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService");
            thr.start();
        }   

        class ServiceWorker implements Runnable
        {
            public void run() {
                // do background processing here...

                long count = 0;
                while (true) {
                    if (count++ > 1000000)
                    {
                        count = 0;
                        Log.d("ServiceWorker", "count reached");
                    }
                }

                //stop the service when done...
                //BackgroundService.this.stopSelf();
            }
        }

        @Override
        public void onDestroy()
        {
            displayNotificationMessage("stopping Background Service");
            super.onDestroy();
        }

        @Override
        public void onStart(Intent intent, int startId) {
            super.onStart(intent, startId);
        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

        private void displayNotificationMessage(String message)
        {
            Notification notification = new Notification(R.drawable.note, message, System.currentTimeMillis());

            PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);

            notification.setLatestEventInfo(this, "Background Service", message, contentIntent);

            notificationMgr.notify(R.id.app_notification_id, notification);
        }
    }

Когда я нажимаю кнопку unbind, unbindBtn, в классе MainActivity я верю, что служба в этом примере будет остановлена. Но из того, что я вижу в logcat, поток, который был запущен службой, продолжает работать. Это похоже на то, что эта нить стала какой-то сиротой, без видимого способа ее остановить. Я видел другой исходный код, использующий цикл while (true) в методе run () потока. Это кажется плохим, если не предусмотрен способ выхода из цикла. Это обычно, как это делается? Или есть другие способы уничтожить поток после того, как служба, которая запустила его, остановилась?

1 Ответ

4 голосов
/ 12 июня 2011

Вы должны предоставить «работающий» boolean.

while(running) {
    //do your stuff
}

Вы хотите сделать его чем-то, что вы можете обновить.Возможно, ваш Service метод onDestroy() должен вызвать метод stopProcessing() на вашем Runnable, который установит для 'running' boolean значение false.

...