java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

3582 ワード

Androidでは、Activityで新しく起動したスレッドがこのActivityのUIコンポーネントにアクセスすることは許可されていません.これにより、新しく起動したスレッドはUIコンポーネントの属性値を変更できません.
Javaが表示されます.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()異常
しかし、実際には、データリフレッシュUIコントロールを非同期で取得する必要がある場合が多く、HandlerメッセージメカニズムとAsyncTask非同期タスクの2つの解決方法が採用されています.
まず、異常を引き起こす例です.
 
new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				
				try {
					Thread.sleep(1000);
					Toast.makeText(getApplicationContext(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0).show();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}).start();

上記の例では、スレッド内で1秒間休眠するとトーストメッセージが表示されjavaが現れる.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()異常.
正しい方法は次のとおりです.
new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				
				try {
					Thread.sleep(1000);
					handler.sendEmptyMessage(0);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
		}).start();
private Handler handler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			
			Toast.makeText(getApplicationContext(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0).show();
			
		}
		
	};

HandlerオブジェクトのhandlerMessageメソッドを書き換えて、必要な処理を行います.
もちろんこの方法だけが私たちのニーズを実現できるわけではありません.
runOnUIThread(Runnable action)Activityに含まれるメソッドでは、指定したactionをUIスレッドで実行し、現在のスレッドがUIスレッドである場合、actionはすぐに実行します.現在のスレッドがUIスレッドでない場合、actionはUIのメッセージキューにイベントを送信します.
View post(Runnable aciton);
View postDelayed(Runnable action, long delayMillis);
この二つの方法も同じ理屈だ.
次は非同期タスクの処理です.
private class MyTask extends AsyncTask<Void, Void, Void> {

		@Override
		protected Void doInBackground(Void... params) {
			// TODO Auto-generated method stub
			publishProgress();
			return null;
		}
		
		@Override
		protected void onProgressUpdate(Void... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
			try {
				Thread.sleep(1000);
				Toast.makeText(getApplicationContext(), "doInBackground", 0).show();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		@Override
		protected void onPostExecute(Void result) {
			// TODO Auto-generated method stub
			Toast.makeText(getApplicationContext(), "onPostExecute", 0).show();
			super.onPostExecute(result);
		}
		
	}

onProgressUpdateメソッドの実行publishProgressメソッド呼び出しを受信した後、UIスレッドで実行し、UIコントロールを処理します.たとえば、私たちが行ったダウンロードは、ダウンロードが何パーセントになったかを表示する必要があります.publishProgress(Value)を停止せずに更新し、進捗バーで更新します.
onPostExecute()メソッドは、doInBackground()メソッドの終了後にUIスレッドで実行され、resultを処理します.
 
doInBackground()メソッドでは、バックグラウンドスレッドで私たちの非同期タスクを処理し、Toastのような操作はできません.javaも出ます.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()異常.