转自:http://blog.csdn.net/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;
- }
- }
-