我有一堆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
答案 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/