E/AndroidRuntime(9916): java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{43805410 V.E..... R.....ID 0,0-1026,288} not attached to window manager
E/AndroidRuntime(9916): at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:370)E/AndroidRuntime(9916): at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:299)
E/AndroidRuntime(9916): at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
E/AndroidRuntime(9916): at android.app.Dialog.dismissDialog(Dialog.java:329)
E/AndroidRuntime(9916): at android.app.Dialog.dismiss(Dialog.java:312)
在将progressDialog 用在ASyncTask中的时候,有时候会遇到上面的错误。
我们先看一下,最常用的AsyncTask中使用ProgressDialog的方法。下面是最常用的使用方法。
public class HttpRequestTask extends AsyncTask <String, Void, String> {
Context ctx = null;
private ProgressDialog dialog = null;
public interface HttpRequestTaskListener {
void ServerResponse (String jsonStr);
}
public HttpRequestTask (final Context c){
ctx = c;
dialog = new ProgressDialog(c);
}
public void addListener (HttpRequestTaskListener l){
listeners.add(0, l);
}
protected void onPreExecute() {
dialog.setMessage("Downloading data from the Server...");
dialog.show();
}
@Override
protected String doInBackground(String... params) {
String url = params[0];
return HttpRequest ( url, .......);
}
@Override
protected void onPostExecute(String result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (listeners.size() > 0){
listeners.get(0).ServerResponse ( result );
}
}
}
一般情况下,上面的方法不会出现任何错误。 任务结束后,ProgressDialog会正常消失。
但是在某些情况下,上面的使用方法就非常不安全。
在项目开发中会遇到在TabView的各个tab page进行切换。同时每个tab page中都会调用
这个异步任务HttpRequestTask去请求网络数据。这时会出现一个问题。
当用户在各个tab page间快速切换的时候,ProgressDialog 使用的context就很不安全。
会遇到调用 dialog.dismiss 和 dialog.show(); 的时候无法attach到Window Manager.
原因是在切换的时候,dialog还没有完成所有的调用,所对应的context已经被destroy或正在destroy。
这时就会导致上面的错误。
尝试解决这个问题。最初想使用ApplicationContext,(context.getApplicationContext()),但是,这个context无法用于ProgressDialog和Toast。会直接导致crash。
目前的解决方法是,先检查context对应的Activity的状态,如果不可用就停止dialog操作:
public class HttpRequestTask extends AsyncTask <String, Void, String> {
Context ctx = null;
private ProgressDialog dialog = null;
public interface HttpRequestTaskListener {
void ServerResponse (String jsonStr);
}
public HttpRequestTask (final Context c){
ctx = c;
dialog = new ProgressDialog(c);
}
public void addListener (HttpRequestTaskListener l){
listeners.add(0, l);
}
protected void onPreExecute() {
if (isValidContext(ctx)){
dialog.setMessage("Downloading data from the Server...");
dialog.show();
}
}
@Override
protected String doInBackground(String... params) {
String url = params[0];
return HttpRequest ( url, .......);
}
@Override
protected void onPostExecute(String result) {
if (isValidContext(ctx) && dialog.isShowing()) {
dialog.dismiss();
}
if (listeners.size() > 0){
listeners.get(0).ServerResponse ( result );
}
}
}
private boolean isValidContext (Context c){
Activity a = (Activity)c;
if (a.isDestroyed() || a.isFinishing()){
Log.i("YXH", "Activity is invalid." + " isDestoryed-->" + a.isDestroyed() + " isFinishing-->" + a.isFinishing());
return false;
}else{
return true;
}
}