开发者

Android - multithreading issues when changing activity

I have a main menu with an action bar. On create, I run a thread that hits my server for a current status. When Complete, the thread calls a handler which kicks off a constantly running thread that cycles through the items and uses another handler call to change the test in the actionbar. The problem is that when I change views, I either get android.view.WindowLeaked or View not attached to window manager

Here is some sample code

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 savedInstanc开发者_如何学CeState) {
        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;
        }
    }
    };
}

I'm not sure if what I'm doing is just wrong or if there is something blatantly obvious that I am missing. What needs to happen is the threads need to stop any time I change screens. Should I use Thread.interrupt(); before starting the next activity?


AsyncTasc allows you to implement doInBackground(), where your thread can crank away at its task. This is similar to the functionality you'd get from Thread.

The real magic happens when you override onPreExecute() and onPostExecute(), which are both executed on the UI thread. This should keep you from getting messages about your Activity not being attached.

Edit - this answer contains a small code example for AsyncTask that could get you started.


You are trying to update UI elements after the owning Activity has been detached from the windowing system.

You will make your life a lot simpler if you use AsyncTask instead of vanilla threads (no handler needed, for one thing) and cancel() the background tasks from your Activity.onPause().


Can't you set a flag in onPause that each of your Threads checks for? If the flag is set then the thread drops out of its loop. Thus whenever the Activity is moved to the background each of your Threads will stop. You would need to handle restarting the threads in onResume. You could alternatively use the AsyncTask approach, but this is not guaranteed to actually cancel when you call its cancel() method, it only attempts to cancel the task.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜