progressDialog not attached to window manager error!

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;
		}
	}



你可能感兴趣的:(progressDialog not attached to window manager error!)