Only the original thread that created a view hierarchy can touch its views异常

写代码的时候碰到android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.这个异常。
异常的意思是说只有创建这个view的线程才能操作这个view,普通会认为是将view创建在非UI线程中才会出现这个错误。
可是在我代码中将view创建在UI线程中也会出现这个错误

下面是我出错的代码:

AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>(){
    		ProgressDialog progressDialog;
			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				progressDialog = new ProgressDialog(getContext());
				progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
				progressDialog.setMessage("请稍后...");
				progressDialog.show();
			}

			@Override
			protected Void doInBackground(Void... params) {
				//耗时操作...
				return null;
			}
			
			@Override
			protected void onPostExecute(Void result) {
				super.onPostExecute(result);
				progressDialog.dismiss();
				
			}
    	};
    	myTask.execute();

  如上,将progressDialog创建在UI进程中还会出现以上错误。

最后在仔细检查时,发现在doInBackground方法里调用了view.invalidate();这个方法。

调用这个方法会调用view的onDraw();方法,从而引起窗口重绘,自然原本的UI进程也被破坏。等到执行完doInBackground后,再调用onPostExecute这个方法执行progressDialog.dismiss();时已经找不到原本创建它的UI进程,自然就会报android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.这个错误了。

另外, 一般引起invalidate()操作的函数如下:

            1、直接调用invalidate()方法,请求重新draw(),但只会绘制调用者本身。

            2、setSelection()方法 :请求重新draw(),但只会绘制调用者本身。

            3、setVisibility()方法 : 当View可视状态在INVISIBLE转换VISIBLE时,会间接调用invalidate()方法,

                     继而绘制该View。

            4 、setEnabled()方法 : 请求重新draw(),但不会重新绘制任何视图包括该调用者本身。

查阅这个异常的相关信息时,发现另外一种情况也可能导致这个异常:

http://my.oschina.net/qixiaobo025/blog/195396

posted @ 2016-08-12 16:20  月出皎兮  阅读(12586)  评论(0编辑  收藏  举报