progressDialog not attached to window manager error!

3771 단어
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에서 Progress 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() {
			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 );
			}
		}
	}

일반적인 상황에서 위의 방법은 어떠한 오류도 발생하지 않을 것이다.작업이 끝나면 Progress Dialog가 정상적으로 사라집니다.
그러나 어떤 경우에는 위의 사용 방법이 매우 안전하지 않다.
프로젝트 개발에서 TabView의 각 tab 페이지를 전환할 수 있습니다.모든 탭 페이지에서 호출됩니다.
이 비동기 작업은 HttpRequestTask에서 네트워크 데이터를 요청합니다.이때 문제가 하나 생길 수 있다.사용자가 각각tab 페이지 사이를 빠르게 전환할 때 Progress Dialog에서 사용하는context는 안전하지 않습니다.대화상자가 호출됩니다.dismiss와 dialog.show(); Windows 관리자에 첨부할 수 없습니다.
전환할 때,dialog가 모든 호출을 완료하지 않았기 때문에, 대응하는context는 이미 destroy되거나 destroy되고 있습니다.
이때 위의 실수를 초래할 수 있다.
이 문제를 해결하려고 시도하다.처음에는 ApplicationContext, (context.get ApplicationContext () 를 사용하고 싶었지만, 이 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;
		}
	}

좋은 웹페이지 즐겨찾기