的Android的AsyncTask范围内的行为
-
22-09-2019 - |
题
我一直工作在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在外部类一>