在后台打开AsyncTask中的托管对话框时的未定义结果

时间:2011-06-07 17:32:27

标签: android multithreading

我遇到一个问题,当用户(或其他应用程序,如电话应用程序)将我的应用程序推送到后台时,会出现一些问题。

我的申请表如下:

  1. 用户可以输入一些应该推送到服务器的信息。
  2. 当用户点击“发送”时,我打开一个托管的ProgressDialog并启动一个执行服务器通信的AsyncTask。
  3. 当服务器通信完成时,AsyncTask向我的Activity报告,我执行dismissDialog()。
  4. 在dismissDialog()之后,我将使用showDialog()显示另一个托管对话框,该对话框将告知用户提交是否正常或是否失败。
  5. 这一切都完美无缺;但是,当AsyncTask运行时发生呼叫时,我得到(看似随机)其中一个结果:

    1. 完全取消持有托管对话框的活动,当我回来时,会显示堆栈中的上一个视图。
    2. 保持托管对话框的活动仍在屏幕上,但在没有显示对话框的情况下显示为灰色。解决此问题的唯一方法是旋转手机,此时它会显示“提交已发送” - 对话方式,完全符合应有的方式,之后一切正常。
    3. 所有这一切都没有任何警告信息,所以我绝对没有任何关于Android为什么会这样做的线索。

      我知道解决这个问题的方法就是取消AsyncTask(因此最后没有显示对话框)。但是,在这个非常小的用例中,要求是应用程序必须尝试完成服务器事务,以便尽可能少地混淆(即用户想知道它是否真的被发送)。

      有没有其他人有这个问题并知道解决方法?

2 个答案:

答案 0 :(得分:1)

我看到建议在onRetainNonConfigurationInstance中保存对asynch任务的引用

What to do with AsyncTask in onPause()?

或实施一辆公共汽车:

https://github.com/commonsguy/cwac-bus/tree

编辑:挑战的复杂性有两个方面:

1)保存并恢复应用程序的状态,例如当有来电时

https://sites.google.com/site/jalcomputing/home/mac-osx-android-programming-tutorial/saving-instance-state

2)以某种方式继续杀死asyncTask而不是取消onPause

https://sites.google.com/site/jalcomputing/home/mac-osx-android-programming-tutorial/asynch

这两项都是重大挑战,试图同时解决这两个问题会让我头疼。事实上,我只是在思考它时会头疼:)一个线索就是你说对话框会在方向改变时返回。这可能是由于使用对话框的标准体系结构,操作系统会在方向更改时处理保存和恢复对话框的状态。

[编辑]参见CommonsWare

@Override
public Object onRetainNonConfigurationInstance() {
    task.detach();
    return(task);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);      
    bar=(ProgressBar)findViewById(R.id.progress);   
    task=(RotationAwareTask)getLastNonConfigurationInstance();  
    if (task==null) {
        task=new RotationAwareTask(this);
        task.execute();
    }
    else {
        task.attach(this);
        updateProgress(task.getProgress());
        if (task.getProgress()>=100) {
            markAsDone();
        }
    }
}

其中task是

的实例
static class RotationAwareTask extends AsyncTask<Void, Void, Void> {

我认为没有理由说这对于所有类型的软杀伤都不起作用,但是对于一次硬杀,你就会被杀死。死了就死了:)。

答案 1 :(得分:0)

如果不查看代码,就很难说出问题所在。但是,您可以使用这些来帮助解决问题。您可以覆盖ActivityonPause()方法。

这是直接来自Android Acitivy javadoc:

  

onPause()是您处理离开活动的用户的地方。最重要的是,此时用户所做的任何更改都应该提交(通常是持有数据的ContentProvider)