Help us understand the problem. What is going on with this article?

Viewの動的生成をUIスレッドで実行するのは間違っている件について

More than 1 year has passed since last update.

TL;DR

  • Viewの作成は別スレッドでも可能。
  • 動的なView生成は別スレッドで実行し、addViewだけUIスレッドで実行するとANR回避できるかも。
  • iOSではXcode9から警告?が出るとのこと。

はじめに

UIスレッドで動的にViewを生成してaddViewするということをしていました。
今まではそれがパフォーマンスに影響するほどの量のViewを生成していなかった、Viewの生成が複雑なロジックではなかったため、問題はありませんでした。
しかし、複雑なロジックでViewの動的生成をする画面が出てきました。
それだけが原因ではないのですが、画面が表示されるまで体感5秒近くかかるし、パフォーマンスが極めて悪いことが分かりました。
これではいかんということで、全体的にロジックを見直し、それに合わせてViewの構築についても見直しすることにしました。

実装

難しいことはしていません。
Viewの生成を別スレッドで実行、生成したViewをコールバックで返すだけです。
Contextなど必要なものはパラメータで渡します。

別スレッド.java
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);
UIスレッド.java
LinearLayout container = findViewById(R.id.container);

for (View view : views) {
    container.addView(view);
}

これで画面にtestと書かれたTextViewが配置されることを確認できました。

おわりに

Viewの生成を別スレッド、addViewはUIスレッドをすることでUIを止めることがなくなります。
Viewの動的生成が複雑な場合にANRを回避できるかも。(そこまで確認してません。)
そもそも動的にViewを作るのであれば、また別の手段を考えるべきなんだろうなぁと思っています。
Contextを渡す必要があるので、メモリーリークしないように対策が必須です。

shmz
Androidアプリ開発をメインにiOSアプリ開発をサブでやっています。 ようやくSwiftを書けるようになってきました。 オリジナルのアイコンがほしいところ。
i-enter
「効果」をつねに提供します。スマホアプリ開発No.1の実績。最新のIoTに対応した開発も行います。
https://www.i-enter.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away