2012年7月26日木曜日

AndroidのHandlerクラスの使い勝手を良くする

Android の Handler クラスの使い勝手が悪いので、改善してみる。

UI 関連の処理をおこないたい場合、(Handler クラスのデフォルトコンストラクタを使うと)「UI スレッド内で Handler インスタンスを作成し、Runnable インスタンスを別途作成して当該 Handler インスタンスの post メソッドに渡す」というコーディングが必要で、そのままコーディングすると次のようになるが、


// UI スレッド
//
// Handler インスタンスを作る。別スレッドで使うというユースケースが
// 大半なので、final を付けることが多くなる。
final Handler handler = new Handler();

// UI スレッドではない別のスレッド
//
// UI に関連する処理をスケジュールする。
handler.post(new Runnable() {
    
public void
 run() {
        
// UI スレッドで実行する処理を記述する。
    }
});

面倒なので、「(1) 常に UI スレッドに紐付けられ、(2) 自クラスで Runnable インターフェースを実装する」Handler クラスのサブクラスを次のように実装してみる。

public class UiHandler extends Handler implements Runnable
{
    
public
 UiHandler()
    {
        
// Looper.getMainLooper() で UI スレッドの Looper を取得する。
        super(Looper.getMainLooper());
    }

    
public
 UiHandler(Handler.Callback callback)
    {
        
// Looper.getMainLooper() で UI スレッドの Looper を取得する。
        super(Looper.getMainLooper(), callback);
    }

    
public boolean
 post()
    {

        // 自分で Runnable インターフェースを実装しているので、
        // post メソッドに this を渡すことができる。
        return post(this);
    }

    
public boolean
 postAtFrontOfQueue()
    {
        
return postAtFrontOfQueue(this
);
    }

    
public boolean postAtTime(Object token, long
 uptimeMillis)
    {
        
return postAtTime(this
, token, uptimeMillis);
    }

    
public boolean postAtTime(long
 uptimeMillis)
    {
        
return postAtTime(this
, uptimeMillis);
    }

    
public boolean postDelayed(long
 delayMillis)
    {
        
return postDelayed(this
, delayMillis);
    }

    
public void
 run()
    {

        // UI スレッドで実行する処理を記述する。
        // サブクラスでオーバーライドすべき。
    }
}

これにより、「任意のスレッド内で」(←面倒削減ポイント)当該サブクラスのインスタンスを作成できる上、Handler と Runnable を別々に管理する必要もなくなり、下記のようなコーディングが可能となる。

new UiHandler() {
    
public void
 run() {
        
// UI スレッドで実行する処理を記述する。
    }
}.post();

0 件のコメント:

コメントを投稿