Handler
解決済
回答 3
投稿
- 評価
- クリップ 0
- VIEW 1,395
コード
public class MainActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);
final TextView tv=new TextView(this);
tv.setText("こんにちは");
layout.addView(tv);
Button button = new Button(this);
layout.addView(button);
button.setText("ボタン");
final Handler handler=new Handler();{
new Thread(new Runnable() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
try{
Thread.sleep(5000);
}
catch(InterruptedException e){
}
tv.setText("別スレッドよりGUIにアクセス");
}
});
}
}).start();
}
}
}
上のプログラムなんですが、これを実行すると5秒後にボタンと文字「別スレッドよりGUIにアクセス」が表示されました。
私は実行すると
「こんにちは」とボタンが表示されて5秒後に「別スレッドよりGUIにアクセス」が表示されると思っていたのですが、なぜこのような動作になるのでしょうか?
また
「こんにちは」とボタンが表示されて5秒後に「別スレッドよりGUIにアクセス」が表示される
このようにするにはどこを改善すればいいのでしょうか?
よろしくお願いします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
ボタンと文字の描画が5秒後になってしまうのは、
描画処理にたどり着く前にThread.sleep(5000)が実行されてしまっているからだと思われます。
処理を順に見ていくと
layout.addView(tv);
layout.addView(button);
でViewを追加していますが、
この段階では、まだ描画処理等は行われておらず、
onCreate()が終わった後のどこかのタイミングでまとめて描画されたと思います。
詳しくは覚えてないので、興味があったら調べてみてください。
final Handler handler=new Handler();
で、Handlerを生成していますが、
Handlerの引数無しコンストラクタを使用して生成した場合、
その処理を呼んだThread(のLooper)に対するHandlerが生成されます。
ActivityのonCreate()は、UIスレッドから呼ばれることになるので、
このHandlerはUIスレッドに対してのHandlerということになります。
new Thread(...).start();
で、新しいThreadを生成した後、即座に実装してあるrun()が実行されます、
つまり
handler.post(...);
が実行されることになるのですが、
このときのhandlerは先ほど生成したUIスレッドに対するHandlerです。
また、post()メソッドを使用して処理を登録しているため、処理遅延無しでの実行となり、
UIスレッドで処理が実行可能になり次第、登録されたran()が実行されます。
最終的に
try{
Thread.sleep(5000);
}catch(InterruptedException e){
}
tv.setText("別スレッドよりGUIにアクセス");
の処理が、スレッドの生成と実行からほとんど遅延無く実行され、
また、実行されるのはもちろんUIスレッドになるので、
UIスレッドでの処理を約5秒間とめた後、文字を更新するということになります。
UIスレッドでは、先ほど追加したViewの描画等の処理が
全てsleep()でとめられてしまっている状態になっており、
sleep()が終わった後、溜まっていた処理が一気に処理され、
同時に処理されているという具合になったのだと思います。
既に回答されている方がいますが、
Thread.sleep(5000);
の処理を消し、
代わりに
handler.post(...);
を
handler.postDelayed(..., 5000)
に変更することで、想定通りの動作になると思います。
適当に書いたので補足等あればお願いします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
なぜこの書き方でボタンが押されてから処理が実行されると思われているのかが気になります。
現在のコードではonCreate内でHandler#startを読んでいるので表示後5秒になっています。
ボタンが押されてからの処理はButton#setInClickListenerでリスナーをセットしないとできません。
該当の処理をOnClicklListener#onClickに記述するとボタンが押されてから5秒後に表示されるようになります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
final Handler handler=new Handler();{
セミコロンで区切られてるので、行末の「{」から後ろはコードブロックとして実行されます。
したがって、onCreateメソッド実行中に5秒間処理停止が走って画面描画が完了するのでは?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/04/05 10:10
postDelayedを使うとできました!