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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM