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

夢とガラクタの集積場

落ちこぼれ三流エンジニアである管理人の夢想=『夢』と、潰えた夢=『ガラクタ』の集積場です。

タイマーが動かなかった理由、判明

昨日困っていた、タイマーが動かなかった件ですが、
実はタイマーが動かなかったのではなく、
Handlerを経由せずにGUIに対してアクセスするタスクを実行していたからでした。
#具体的にGUIアクセスしている個所は★参照

Handlerってなんじゃらほい、と思って調べてみると、
throw Life:AndroidのHandlerとは何か?に、解説が。

実は、AndroidGUIはシングルスレッドで動いており、
画面に対してアクセスが可能なのはメインスレッドだけ、とのこと。
で、メインスレッド以外がアクセスすると例外(CalledFromWrongThreadException)吐くそうな。
今回の場合、CatchしているのがRemoteExceptionだけなので、
当然runから例外が飛び出してジエンド、という。

なので、タイマーからGUIを操作したい場合は
何かしらの形でメインスレッドに処理を委譲する必要があるわけでして。
その委譲を行ってくれるのがHandlerだそうな。
なるほどねぇ。。。GUIといっても、Swingとはこの辺りは全然違う。

ただ、気になるのはボタンにイベント定義してリスナ仕込んだ場合は
特にHandlerにpostしなくてもGUIに対する操作が動くんですよね。
てことは、タイマーから叩くのは別スレッドだけど、リスナから呼び出される場合は
メインスレッドを経由して実行されるということなのかな?
ただ、リスナって待ち受けスレッド用意するようなものだからなぁ。。。はてさて。

一度Androidのスレッドモデルについて調べてみる必要がありそうだなぁ。

とりあえず、明日デバッグかけて確認してみます。

===
            TimerTask timerTask = new TimerTask() {
                public void run()
                {
                    try
                    {
                        Toast toast = Toast.makeText(getApplicationContext(), "Count Start", ★ここ★
                                Toast.LENGTH_SHORT);
                        toast.show();
                        targerCallback.updateTimerText();
                    }
                    catch (RemoteException e)
                    {
                        e.printStackTrace();
                        Toast toast = Toast.makeText(getApplicationContext(), "Count Failed",
                                Toast.LENGTH_SHORT);
                        toast.show();
                    }
                }
            };
===