Android的AsyncTask的环境行为行为、环境、Android、AsyncTask

由网友(倾我至诚)分享简介:我一直使用Android中AsyncTasks和我处理的一个问题。I've been working with AsyncTasks in Android and I am dealing with an issue.举一个简单的例子,一个活动有一个AsyncTask的。在后台的任务没有做任何事情壮观,它只是睡,持...

我一直使用Android中AsyncTasks和我处理的一个问题。

I've been working with AsyncTasks in Android and I am dealing with an issue.

举一个简单的例子,一个活动有一个AsyncTask的。在后台的任务没有做任何事情壮观,它只是睡,持续8秒。

Take a simple example, an Activity with one AsyncTask. The task on the background does not do anything spectacular, it just sleeps for 8 seconds.

在AsyncTask的在onPostExecute()方法,我只设置一个按钮的可见性状态View.VISIBLE,只是为了验证我的结果。

At the end of the AsyncTask in the onPostExecute() method I am just setting a button visibility status to View.VISIBLE, only to verify my results.

现在,这个伟大工程,直到用户决定改变他的手机的方向而AsyncTask的是工作(在8秒的睡眠窗口)。

Now, this works great until the user decides to change his phones orientation while the AsyncTask is working (within the 8 second sleep window).

我明白了Android活动的生命周期,我知道活动被破坏并重新创建。

I understand the Android activity life cycle and I know the activity gets destroyed and recreated.

这是哪里出了问题用武之地。的AsyncTask是指一个按钮,显然持有引用,开始了AsyncTask的摆在首位的背景下。

This is where the problem comes in. The AsyncTask is referring to a button and apparently holds a reference to the context that started the AsyncTask in the first place.

我所期望的,这个旧的上下文(因为用户造成的方向变化),要么成为空和AsyncTask的抛出NPE的参考按钮,它正在努力使可见。

I would expect, that this old context (since the user caused an orientation change) to either become null and the AsyncTask to throw an NPE for the reference to the button it is trying to make visible.

相反,没有NPE被抛出,在AsyncTask的认为,该按钮引用不为空,将它设置为可见。结果?什么也没有发生在屏幕上!

Instead, no NPE is thrown, the AsyncTask thinks that the button reference is not null, sets it to visible. The result? Nothing is happening on the screen!

更新:我已经通过保持一个的WeakReference 的活动和切换时的配置发生了变化解决这一点。这是麻烦的。

Update: I have tackled this by keeping a WeakReference to the activity and switching when a configuration change happens. This is cumbersome.

这里的code:

public class Main extends Activity {

    private Button mButton = null;
    private Button mTestButton = null;

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

        mButton = (Button) findViewById(R.id.btnStart);
        mButton.setOnClickListener(new OnClickListener () {
            @Override
            public void onClick(View v) {
                new taskDoSomething().execute(0l);
            }
        });
        mTestButton = (Button) findViewById(R.id.btnTest);   
    }

    private class TaskDoSomething extends AsyncTask<Long, Integer, Integer> 
    {
        @Override
        protected Integer doInBackground(Long... params) {
            Log.i("LOGGER", "Starting...");
            try {
                Thread.sleep(8000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 0;
        }

        @Override
        protected void onPostExecute(Integer result) {
            Log.i("LOGGER", "...Done");
            mTestButton.setVisibility(View.VISIBLE);
        }
    }
}

试着执行它,而AsyncTask的正在改变你的手机的方向。

Try executing it and while the AsyncTask is working change your phones orientation.

推荐答案

AsyncTask的目的不是一次的活动已被拆除,并重新得到重用。内部处理器的对象变得陈旧,就像你说。在货架例如,通过罗曼盖伊,他简单的将取消任何正在运行的AsyncTask的,然后重新启动新的后方向的改变。

AsyncTask is not designed to be reused once an Activity has been torn down and restarted. The internal Handler object becomes stale, just like you stated. In the Shelves example by Romain Guy, he simple cancels any currently running AsyncTask's and then restarts new ones post-orientation change.

有可能手头宽裕的主题为新的活动,但它增加了不少水管。没有普遍同意的方式来做到这一点,但你可以看到这里我的方法:http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html

It is possible to hand off your Thread to the new Activity, but it adds a lot of plumbing. There is no generally agreed on way to do this, but you can read about my method here : http://foo.jasonhudgins.com/2010/03/simple-progressbar-tutorial.html

阅读全文

相关推荐

最新文章