今日の記事は、Androidアプリ開発中に遭遇したエラーについてです。
修正はそこまで大変ではなかったのですが、使用頻度が低く、忘れそうだったので備忘録としてまとめます。
エラーは「Only the original thread that created a view hierarchy can touch its views.」というもので、こちらはメインスレッド以外で、TextView などの UI を変更しようとすると発生するエラーです。
シンタックスエラーとは違い、ビルドは通ってしまうので要注意ですね。
では、早速対処法についてご紹介。
今回参考にさせていただいたサイトはこちらです。
メインスレッド以外でUIを変更する方法 – Accele Biz IT開発技術 調査報告書
http://accelebiz.hatenablog.com/entry/2016/09/01/061934
エラーが発生したコードはこちら。
TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.[ID名]); showMessage(); } private void showMessage(){ try { /* 処理 */ textView.setText("[表示したい文字列]"); } catch (JSONException e) { e.printStackTrace(); } }
一部改変していますが、だいたいこんな感じ。
で、問題は、showMessage() 内の try/catch で指定した、setText() です。
やった事がなかったので知らなかったのですが、このようにメインスレッド以外で UI を操作することはできないようでした。
ですが、対処法もちゃんと用意されていました。
参考サイトそのままですが、Handler を使用して、別スレッドからメインスレッドに処理を依頼する方法です。
具体的には下記のとおりです。
private void showMessage(){ final Handler mainHandler = new Handler(Looper.getMainLooper()); try { /* 処理 */ mainHandler.post(() -> { textView.setText("[表示したい文字列]"); }); } catch (JSONException e) { e.printStackTrace(); } }
2行目に Handler を宣言し、TextView の操作の記述を mainHandler.post()
で囲うだけです。
これを追加したところ、問題なく TextView の操作を行うことができました。
以上、TextView などの UI の操作をメインスレッド以外から行う方法でした。
今回の解決策は、例えば何らかの処理を別スレッド&非同期で行っていて、結果が返ってきたタイミングで UI を変更したい、等の場合にも使えるかと思います。
もし、同じエラーでお困りの場合は、是非参考にしていただければと思います。