Android - проблемы многопоточности при смене активности - PullRequest
1 голос
/ 04 марта 2011

У меня есть главное меню с панелью действий. При создании я запускаю поток, который попадает на мой сервер для текущего состояния. Когда Завершено, поток вызывает обработчик, который запускает постоянно работающий поток, который циклически перебирает элементы и использует другой вызов обработчика, чтобы изменить тест на панели действий. Проблема в том, что когда я меняю представления, я получаю android.view.WindowLeaked или View not attached to window manager

Вот пример кода

public class MainMenuActivity extends ProtectedWithActionBarActivity{
    private int STATUS_COUNTER;
    private final int RESULT_STATUS_LOADED = 2000;
    private final int RESULT_SHOW_STATUS = 2001;
    private CurrentStatusModel currentStatus;

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

        setContentView(R.layout.mainmenu);

        ActionBar footerbar = (ActionBar)findViewById(R.id.footerbar);

        footerbar.setTitle("Currently connected to " + PreferencesHelper.getCurrentEnvironment().name());


        STATUS_COUNTER = 0;

        statusLoadThread.start();
    }

    Thread statusLoadThread = new Thread()
    {
        @Override
        public void run()
        {
            //set currentStatus with data from server
        }
    };

    Thread statusDisplayThread = new Thread()
    {
        int sleep = 5000;
        boolean threadDone = false;

        public void done()
        {
            threadDone = true;
        }

        @Override
        public void run()
        {
            while(true)
            {
                //pick message to send to handler
                //increment STATUS_COUNTER or reset to 0 when out of bounds

                try 
                {
                    sleep(sleep);
                } 
                catch (InterruptedException e) 
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch(msg.what)
        {
            case RESULT_STATUS_LOADED:
                statusDisplayThread.start();
                break;
            case RESULT_SHOW_STATUS:
                ActionBar footerbar = (ActionBar)findViewById(R.id.footerbar);

                String message = ((Object[])msg.obj)[0].toString();
                OnClickListener listener = (OnClickListener)((Object[])msg.obj)[1];

                footerbar.setTitle(message);
                    footerbar.setOnTitleClickListener(listener);

                break;
            case ActivityBase.RESULT_ERROR:

                break;
        }
    }
    };
}

Я не уверен, что то, что я делаю, просто неправильно или есть что-то явно очевидное, что я упускаю. Что должно произойти, так это то, что потоки должны быть остановлены при каждой смене экранов Должен ли я использовать Thread.interrupt(); перед началом следующего занятия?

Ответы [ 3 ]

1 голос
/ 04 марта 2011

AsyncTasc позволяет реализовать doInBackground(), где ваша нить может проворачиваться при выполнении своей задачи. Это похоже на функциональность, которую вы получите от Thread.

Настоящее волшебство происходит, когда вы переопределяете onPreExecute() и onPostExecute(), , которые оба выполняются в потоке пользовательского интерфейса . Это должно помешать вам получать сообщения о том, что ваша активность не привязана.

Редактировать - этот ответ содержит небольшой пример кода для AsyncTask, который может помочь вам начать работу.

0 голосов
/ 04 марта 2011

Не можете ли вы установить в onPause флаг, который проверяет каждый из ваших Thread s?Если флаг установлен, то поток выпадает из своего цикла.Таким образом, всякий раз, когда Activity перемещается на задний план, каждый из ваших Thread s останавливается.Вам потребуется обработать перезапуск потоков в onResume.В качестве альтернативы вы можете использовать подход AsyncTask, но это не гарантирует фактической отмены при вызове его метода cancel(), он только пытается отменить задачу.

0 голосов
/ 04 марта 2011

Вы пытаетесь обновить элементы пользовательского интерфейса после того, как собственное действие было отсоединено от оконной системы.

Вы сделаете свою жизнь намного проще, если вместо AsyncTaskванильные потоки (без необходимости, обработчик) и cancel() фоновые задачи из вашего Activity.onPause().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...