转自:http://blog.youkuaiyun.com/yuxiaohui78/article/details/38076447
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 ; } }