我一直工作在Android的AsyncTasks和我处理的一个问题。

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

目前()中的的AsyncTask在onPostExecute方法,我只设置一个按钮能见度状态View.VISIBLE,只能验证我的结果。的端

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

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

这是问题用武之地。的AsyncTask指的是一个按钮,显然保持于在所述第一位置开始的AsyncTask的上下文的引用。

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

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

<强>更新我通过保持WeakReference到活动,并且当配置改变发生切换解决这一点。这是麻烦的。

下面的代码:

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正在改变你的手机的方向。

有帮助吗?

解决方案

的AsyncTask没有设计一旦活动已被拆除和重新启动将被重复使用。内部处理器对象变得陈旧,就像你说。在由罗曼盖伊密集架例子,他简单的取消所有正在运行的AsyncTask的,然后重新启动新的后期取向的变化。

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

其他提示

如果你只需要一个框架,并且对用户界面的东西,你可以简单地通过ApplicationContext来你AsyncTask.You往往需要对系统资源的情况下,例如,将不会使用它。

不要尝试更新从的AsyncTask用户界面,并尽量避免处理配置改变自己,因为它会导致混乱。为了更新您可以登记的广播接收器的UI和发送广播。

您也应该具有的AsyncTask从活动的独立公共类如上面提到的,它使测试更加容易。不幸的是Android的编程往往强化了不良做法和官方的例子没有帮助。

这是一件事情使我总是阻止我的活动被销毁/重建与方向变化的类型。

这样做这在您的清单文件添加到您的<Activity>标签:

android:configChanges="orientation|keyboardHidden" 

和覆盖你的动态类onConfigurationChanged:

@Override
public void onConfigurationChanged(final Configuration newConfig)
{
    // Ignore orientation change to keep activity from restarting
    super.onConfigurationChanged(newConfig);
}

要避免这一点,你可以在这里使用的答案得到安宁: https://stackoverflow.com/a/2124731/327011

但是,如果你需要销毁活动(不同的布局纵向和横向)可以使的AsyncTask一个公共类(读到这里,为什么它不应该是私有的安卓的AsyncTask建议:私有类或公共类),然后创建一个方法setActivity设置参考电流活动时,它被破坏/创建。

可以在这里看到的例子:的Android的AsyncTask在外部类

scroll top