質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

2241閲覧

フラグメント上で、Threadを使うRunnableを実装したい。

aruko

総合スコア47

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2021/11/28 09:39

androidstudioでゲーム作りをしています。
フラグメント上でアニメーションを多用します。
ビューアニメーションやプロパティアニメーションは、ここで教えてもらってフラグメント上でも表示できるようになりました。
アニメーションの中には、同じアニメーションを、〇秒後、△秒後、□秒後というようにずらしながら20回くらいアニメーションさせるものもあります。
そこで、以前パソコンで行うアプリを作っていた時に使用したimplements Runnableを用いて、count秒後にアニメーションを開始できるようThreadを使って、まずはフラグメント上でテキストビューにcountを表示させたいです。
実行してみましたが、一瞬画面が現れてからすぐ消えてしまう、という状態です。
どのようにしたらよいか、教えていただきたいです。

MainFragment.javaです。

java

1public class MainFragment extends Fragment implements Runnable{ 2 3 TextView frma_tv8; 4 int count; 5 Thread thread; 6 @Override 7 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 8 return inflater.inflate(R.layout.fragment_main, container, false); 9 } 10 11 @Override 12 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 13 super.onViewCreated(view, savedInstanceState); 14 15 MainViewModel vm = new ViewModelProvider(requireActivity()).get(MainViewModel.class); 16 frma_tv8=view.findViewById(R.id.frma_tv8); 17 frma_tv8.setText("count="+String.valueOf(count)); 18     thread=new Thread(this); 19 thread.start(); 20 21 } 22 public void start(){ 23 if(thread==null){ 24 thread=new Thread(this); 25 thread.start(); 26 } 27 } 28 public void stop(){ 29 if(thread!=null){thread=null;} 30 } 31 @Override 32 public void run() { 33 Thread thisThread=Thread.currentThread(); 34 while (thread!=null){ 35 count++; 36 frma_tv8.setText("count="+String.valueOf(count)); 37 try{ 38 thread.sleep(1000); 39 }catch (InterruptedException e){} 40 } 41 } 42} 43

fragment_main.xmlには、テキストビューfrma_tv8があります。
Runnableを実装させていない時は、実行するとフラグメント上にちゃんと表示できていました。
Runnableを実装させるとうまくいきません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/11/28 10:17

>実行してみましたが、一瞬画面が現れてからすぐ消えてしまう、という状態 その時、 logcat に例外は出ていませんでしょうか。
aruko

2021/11/28 10:37

いつもほんとに力になってくださりありがとうございます。 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8376) at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1442) at android.view.View.requestLayout(View.java:25014) at android.view.View.requestLayout(View.java:25014) at android.view.View.requestLayout(View.java:25014) at android.view.View.requestLayout(View.java:25014) at android.view.View.requestLayout(View.java:25014) at android.view.View.requestLayout(View.java:25014) at android.view.View.requestLayout(View.java:25014) at androidx.constraintlayout.widget.ConstraintLayout.requestLayout(ConstraintLayout.java:3593) at android.view.View.requestLayout(View.java:25014) at android.widget.TextView.checkForRelayout(TextView.java:9711) at android.widget.TextView.setText(TextView.java:6289) at android.widget.TextView.setText(TextView.java:6117) at android.widget.TextView.setText(TextView.java:6069) at tmaruko.okura.jiisan.MainFragment.run(MainFragment.java:106) at java.lang.Thread.run(Thread.java:919) というエラーです。 MainFragment.java:106とは、上記のコード内では、 public void run() { 内の、 frma_tv8.setText("count="+String.valueOf(count)); です。
jimbe

2021/11/28 12:10

例外等のメッセージは問題を把握する上で最需要な情報ですので、何か起きたらまずは logcat 等を確認されて、そのメッセージからまずは原因の特定をお試しください。 また、ご質問の際は予め本文にご提示頂くと回答もスムーズになると思います。
guest

回答1

0

ベストアンサー

Only the original thread that created a view hierarchy can touch its views.

「ビュー階層を作成した元のスレッドのみがそのビューに触れることができます。」(Google 翻訳)

というメッセージの通り、設計上 Android では UI スレッドで無ければ View を更新するメソッドは使えません。(つまりこれは Fragment は関係ありません。)

このような場合は Handler を使って UI スレッドに実行を依頼することで対処できます。
例えば以下のような記事で紹介されています。
【Android】「Only the original thread that created a view hierarchy can touch its views.」の対処法

なお、 Handler には postDelayed という「一定時間後に実行するように依頼する」メソッドもありますので、テキトウな時間間隔で実行するならこちらの利用も検討に値するかと思います。

投稿2021/11/28 12:05

編集2021/11/28 12:15
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momodx

2021/11/28 12:20

余談となりそうですが、こんな方法もあります: > ただし、UI スレッドまたは「メイン」スレッド以外のスレッドから UI を更新することはできません。 > この問題を修正するために、 > Android には、他のスレッドから UI スレッドにアクセスする方法がいくつか用意されています。 > 使用できるメソッドは次のとおりです。 > ・Activity.runOnUiThread(Runnable) > ・View.post(Runnable) > ・View.postDelayed(Runnable, long) プロセスとスレッドの概要 - ワーカー スレッド [Android Developers] より https://developer.android.com/guide/components/processes-and-threads?hl=ja#WorkerThreads
jimbe

2021/11/28 12:36

momodx さん情報ありがとうございます。 自分でも postDelayed まで書いておいて何ですが、Fragment でのことですので、ベストとしては、 count を ViewModel の LiveData にして更新は UIスレッド上からの set か new Thread (等) からの post で行って TextView への表示は observe でする…かもしれませんね。
aruko

2021/11/28 12:48

できました。 いくつかのサイトでHandlerのことが書いてありましたが、そういうことだったのですね。 jimbeさん、またまたありがとうございました。 momodxさん、アドバイスありがとうございます。 サイトで調べるとThreadを使う場合のコードの書き方が色々あって、結局どれを使うのか分からない、という感じでした。 実際、いくつかの方法があるということですね。 またよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問