TL;DR
- Viewの作成は別スレッドでも可能。
- 動的なView生成は別スレッドで実行し、addViewだけUIスレッドで実行するとANR回避できるかも。
- iOSではXcode9から警告?が出るとのこと。
はじめに
UIスレッドで動的にViewを生成してaddViewするということをしていました。
今まではそれがパフォーマンスに影響するほどの量のViewを生成していなかった、Viewの生成が複雑なロジックではなかったため、問題はありませんでした。
しかし、複雑なロジックでViewの動的生成をする画面が出てきました。
それだけが原因ではないのですが、画面が表示されるまで体感5秒近くかかるし、パフォーマンスが極めて悪いことが分かりました。
これではいかんということで、全体的にロジックを見直し、それに合わせてViewの構築についても見直しすることにしました。
実装
難しいことはしていません。
Viewの生成を別スレッドで実行、生成したViewをコールバックで返すだけです。
Contextなど必要なものはパラメータで渡します。
List<View> views = new ArrayList<>();
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
TextView textView = new TextView(context);
textView.setLayoutParams(params);
textView.setText("test");
views.add(textView);
LinearLayout container = findViewById(R.id.container);
for (View view : views) {
container.addView(view);
}
これで画面にtestと書かれたTextViewが配置されることを確認できました。
おわりに
Viewの生成を別スレッド、addViewはUIスレッドをすることでUIを止めることがなくなります。
Viewの動的生成が複雑な場合にANRを回避できるかも。(そこまで確認してません。)
そもそも動的にViewを作るのであれば、また別の手段を考えるべきなんだろうなぁと思っています。
Contextを渡す必要があるので、メモリーリークしないように対策が必須です。