使用背景崩溃应用程序中的对话框

时间:2012-12-22 00:15:48

标签: android android-layout

我有一堆AsyncTasks来获取数据。它们通过显示对话框来更新正在执行的进度。有时这会导致应用程序在应用程序处于后台(不可见)时崩溃。我的代码在下面调用。如果不完全重新分解对话框,我可以做些什么来阻止应用程序崩溃?

这些在DownloadAsyncTask中声明,并在构造函数

上传递
protected ProgressDialog mDialog;
protected String mDialogMessage = "Loading Data";
protected ProgressBar progBar;

doInBackground() {
    if ( mProgressBar != null && mProgressBar.getVisibility() == View.INVISIBLE) {
        mUIThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                mProgressBar.setVisibility(View.VISIBLE);
            }
        });
    } else if ( mDialog != null && !mDialog.isShowing() ) {
        mUIThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                mDialog.setMessage(mDialogMessage);
                mDialog.show();
            }
        });
    }
}

然后onPostExecute()

@Override
protected void onPostExecute(DefaultHandler handler) {
    super.onPostExecute(handler);
    if ( progBar != null && progBar.getVisibility() == View.VISIBLE ) {
        progBar.setVisibility(View.INVISIBLE);
    } else if ( mDialog != null && mDialog.isShowing() ) {
        try {
            mDialog.dismiss();
        } catch (Exception e) {
        }   
    }   
}

更新的崩溃日志:

  

12-20 15:19:15.802:E / AndroidRuntime(9529):
  android.view.WindowManager $ BadTokenException:无法添加窗口 -   令牌android.os.BinderProxy@41a37908无效;是你的活动   运行? 12-20 15:19:15.802:E / AndroidRuntime(9529):at   android.view.ViewRootImpl.setView(ViewRootImpl.java:567)12-20   15:19:15.802:E / AndroidRuntime(9529):at   android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:246)   12-20 15:19:15.802:E / AndroidRuntime(9529):at   android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)   12-20 15:19:15.802:E / AndroidRuntime(9529):at   android.app.Dialog.show(Dialog.java:281)12-20 15:19:15.802:   E / AndroidRuntime(9529):at   com。*。DownloadAsyncTask $ 2.run(DownloadAsyncTask.java:119)12-20   15:19:15.802:E / AndroidRuntime(9529):at   android.os.Handler.handleCallback(Handler.java:725)12-20   15:19:15.802:E / AndroidRuntime(9529):at   android.os.Handler.dispatchMessage(Handler.java:92)12-20   15:19:15.802:E / AndroidRuntime(9529):at   android.os.Looper.loop(Looper.java:137)12-20 15:19:15.802:   E / AndroidRuntime(9529):at   android.app.ActivityThread.main(ActivityThread.java:5039)12-20   15:19:15.802:E / AndroidRuntime(9529):at   java.lang.reflect.Method.invokeNative(Native Method)12-20   15:19:15.802:E / AndroidRuntime(9529):at   java.lang.reflect.Method.invoke(Method.java:511)12-20 15:19:15.802:   E / AndroidRuntime(9529):at   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run

3 个答案:

答案 0 :(得分:1)

您正在从后台主题中触摸UI。 Android技术上说“不要更新”,但最好将其读作“不与后台线程上的UI交互”。您的if语句基本上表示“if(...)对于UI是正确的,将此任务发布到将来某个时间在UI线程上执行”。当您的Runnable在UI线程上执行时,UI的状态可能已更改。最好将封装整个逻辑并将其发送到要执行的UI线程。你可以通过组合你拥有的两个Runnable并在一个post中发货来实现这一点,但AsyncTask的设计是为了让你不需要直接处理处理程序。如果您在doInBackGround中调用publishProgress(),它会在UI线程上向onProgressUpdate()成员发出一个调用。因此,更容易做的是合并Runnable中的代码并转到onProgressUpdate()方法。

像 -

   void onProgressUpdate() {
            if (mProgressBar != null && mProgressBar.getVisibility() == View.INVISIBLE) {
                mProgressBar.setVisibility(View.VISIBLE);
            } else if (mDialog != null && !mDialog.isShowing()) {
                mDialog.setMessage(mDialogMessage);
                mDialog.show();
            }
        }

答案 1 :(得分:0)

使用runOnUiThread(runnable)来避免崩溃:这实际上是在UI线程的run方法中运行代码段。包含您想要在run方法中执行的所有UI操作,如下所示。

所以代码会像:

yourActivity.runOnUiThread(new Runnable(){

            @Override
            public void run() {
                // whatever UI operations..
                ..
                mDialog.setMessage(mDialogMessage);
                mDialog.show();
            }

});

答案 2 :(得分:0)

您应该检查活动是否完成。

使用此:

if (!isFinishing()) {
    mDialog.show();
    }

检查此页面以获取更多描述:

http://dimitar.me/android-displaying-dialogs-from-background-threads/