読者です 読者をやめる 読者になる 読者になる

Handler

ThreadとRunnableを使って、重たい処理を別のスレッドに任せることができた・・・。
そのスレッドの処理が終ったら、TextViewやButtonの状態、Toast表示などで終わったことを通知したい・・・。

package com.bgstation0.android.sample.handler_;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{	// View.OnClickListenerを実装.

	// メンバフィールドの定義.
	private final String TAG = "Handler_";	// TAG"Handler_"の定義.
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // button1を取得し, OnClickListenerとして自身をセット.
        Button button1 = (Button)findViewById(R.id.button1);	// findViewByIdでR.id.button1を取得.
        button1.setOnClickListener(this);	// button1.setOnClickListenerでthis(自身)をセット.
    }
    
    // View.OnClickListenerインタフェースのオーバーライドメソッドを実装.
    public void onClick(View v){	// onClickをオーバーライド.
    
    	// 匿名クラスでRunnableを実装したThreadを生成して開始.
    	new Thread(new Runnable(){	// Threadオブジェクトを生成, 引数にRunnableを継承した匿名クラスオブジェクトを渡す.(使い捨てなら参照を変数に格納しなくていい.)
    		public void run(){	// Runnable.runをオーバーライド.
    			// 10秒たったらButton1のテキストを"Pushed!"に変える.
    			try{
    	    		Thread.sleep(10000);	// Thread.sleepで10秒休止.
    	    		Button button1 = (Button)findViewById(R.id.button1);	// findViewByIdでR.id.button1を取得.
    	    		button1.setText("Pushed!");	// button1.setTextで"Pushed!"に変更.
    	    	}
    	    	catch(Exception ex){
    	    		Log.d(TAG, "ex = " + ex.toString());	// Log.dでexを出力.
    	    	}
    		}
    	}).start();	// startで開始.
    	
    }
}

このように10秒経ったら、button1のテキストを"Pushed!"に変えたい・・・。

f:id:BG1:20161004145911p:plain

しかし、Button1を押しても変わらない・・・。

f:id:BG1:20161004145955p:plain

Exceptionが出て失敗している・・・。
CalledFromWrongThreadException・・・。
新しく作ったワーカースレッドからUIスレッドのモノへはアクセスできないのである・・・。

そこで、Handlerを使って、UI変更処理はUIスレッドに任せるようにする・・・。

Handler | Android Developers

MainActivityで、

Handlerオブジェクトhandlerをメンバフィールドとして用意・・・。(別にメンバじゃなくてもいいのだが一応・・・。)
onClickでnewでHandlerオブジェクトhandlerを生成・・・。
そしたら、Thread内のrunの中でThread.sleepが終ったら、handler.postにRunnableの匿名クラスオブジェクトを渡し、その定義のrunの中でUI変更処理を行う・・・。
button1.setTextで"Pushed!"に・・・。
handler.postによって、渡されたRunnableのrunの処理はhandlerが生成されたスレッドで行われる・・・。
newした位置はThreadの外側なので、UIスレッドということになる・・・。

f:id:BG1:20161004151829p:plain

改めて、Button1を押すと、

f:id:BG1:20161004151855p:plain

"Pushed!"に変わった・・・。

https://github.com/bg1bgst333/Sample/tree/master/android/Handler/Handler/src/Handler