原因
おそらくhandlerは次のような定義をしておられるだろうと思います。
Kotlin
1class MainActivity : AppCompatActivity() {
2 // (A)
3 val handler = Handler(Looper.getMainLooper()) // コンストラクター引数を省略しているかも
4 ...
5}
こうなっているとこのハンドラーへのpostはUIスレッドで実行されます。つまり
重い処理が完了するまでonCreateが完了しないように見えています
という質問者さんの推測どおりの動きになっていると思います。
本件のように「1回こっきりのバックグランド処理」にThreadを用いるのは理にかなっていると思いますが、単なるThreadに対してHandler#postでバックグラウンド処理を頼むことはできません。なぜならHandler#postは実行すべき処理をスレッドに結び付いたメッセージキューに繋げることで機能を実装しており、単なるTheadはこのメッセージキューを持っていないからです。
(HandlerThreadならばメッセージキューを持ってますのでHandler#postが行えますが、1回こっきりのバックグラウンド処理にHandlerThreadは合わないと思います。)
対処
Threadを用いるとき、そのスレッド上で動作する処理をどこに指定すればよいかというと以下のどちらかとするのが普通です。
- コンストラクターの引数
- Threadのrunメソッド本体
またUIスレッド以外のスレッドからviewへのアクセスには
- (ア) 前述の(A)のような定義のhandlerへのpostによる
- (イ) Viewインスタンスのpostメソッドによる
- (ウ) ActivityインスタンスのrunOnUiThreadメソッドによる
などの方法があるようです。本件ですとhandlerをわざわざ定義せずとも(イ)や(ウ)でよい気がします。
Kotlin
1class MainActivity : AppCompatActivity() {
2 val handler = Handler(Looper.getMainLooper())
3
4 override fun onCreate(savedInstanceState: Bundle?) {
5 ...
6 val view = findViewById<...>(...)
7
8 Thread {
9 // 重い処理
10 ...
11 view.post {
12 // viewへ計算結果を反映
13 view.なんたらかんたら
14 }
15 }.start()
16 }
17
18 ...
19}
余談
回答を書いていて自分にわからない点がありました。
onCreateが終わった後にユーザー操作やシステムの状態の変化などでこのActivityの状態が休止(pause)状態や停止(stop)状態になることを想定すべきと思うのですがそれってどうやるんでしょう・・・
onPause/onStopなどでバックグラウンド処理中だったら割り込みによりバックグラウンド処理を速やかに中断し、onResumeで再度開始なんて筋書きにするのでしょうか・・・
残念ながらAndroidに暗いのではっきりした方法がわかりませんでした。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/01/12 12:14
2019/01/13 04:42
2019/01/13 04:54