liguofeng29’s blog

個人勉強用ブログだっす。

Androidのイベント処理 - Handler

 パフォーマンス面の考慮でAndroidのUI操作はスレッドセーフではない。

 
これによって複数のスレッドでUI操作が行われるとスレッドセーフの問題が発生する。
これを解決するためにAndroidは一つのルールを決めてある。

 

「UIスレッドのみActivity内のUIを変更できる」
 
 
アプリが初めて起動される時、Androidはメインスレッドを起動する。
メインスレッドは主にUI関連の処理を行う(クリックイベント、タッチイベントなど)、
なのでメインスレッドをUIスレッドと呼ぶことが多いらしい。

 

でも、実際アプリでは複数のスレッドでUIを変更する必要があるのだ。
 
これを解決するための仕組みが「Handler」である。

 

Handlerクラスの役割

① サブスレッドでメッセージを送る
② UIスレッド(Main thread)でメッセージ取得&処理
 
 
Handlerクラスのメソッド

void handleMessage(Message msg)

                            - メッセージを処理。通常オーバライドされる。

final boolean hasMessage(int what)

                            - MessageQueueにwhat属性のメッセージがあるのか

final boolean hasMessage(int waht, Object object) 

                                         - MessageQueueにwhat属性のobjectメッセージがあるのか

Message obtainMessage() - Message取得
sendEmptyMessage(int what) - 空メッセージを送る
final boolean sendEmptyMessageDelayed(int what, long delayMillis)

                            - Xミリ秒後空メッセージを送る

final boolean sendMessage(Message msg) - 即時メッセージを送る
final boolean sendMessageDelayed(Message msg, long delayMillis)

                            - Xミリ秒後メッセージを送る

 

 

下記サンプルコードでは自動で画像切り替える。

MainActivity.java
 
package com.example.liguofeng.firsthandler;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

private int currentImage = 0;
// 画像リソース
final int[] images = new int[]{
R.drawable.img1,
R.drawable.img2,
R.drawable.img3,
R.drawable.img4
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final ImageView view = (ImageView) findViewById(R.id.view);

// ハンドラー
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
// 画像表示
view.setImageResource(images[currentImage++ % images.length]);
}
super.handleMessage(msg);
}
};

// タイマー設定(サブスレッド)
new Timer().schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
}
}, 0, 500);
}
}