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