teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

8

コード修正

2021/12/03 19:26

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -12,7 +12,8 @@
12
12
 
13
13
  ----
14
14
  次のようなコードにすれば、実行時のプログラムの動作が logcat に出ますので、画面を off にしてみたりして確認してみてください。
15
- Handler で post するオブジェクトを remove できるように使い回すようにし、 count をオブジェクト移動させることでスレッド実行にはまた最初からなるようにしています。
15
+ Handler で post するオブジェクトを念の為 remove るようにし、 count をタイマースレッド定義することで再始動の count のリセットとしています。
16
+ スレッドの停止も interrupt に対応しました。
16
17
 
17
18
  (EmptyActivity から作ったプロジェクトで、 Hello World! を表示していた TextView に ```android:id="@+id/textView"``` を加えて使っています。)
18
19
 
@@ -66,39 +67,44 @@
66
67
  public void stop(){
67
68
  Log.d("MainActivity","stop()");
68
69
  if(thread != null) {
69
- Thread t = thread;
70
- thread = null;
71
- t.interrupt();
70
+ thread.interrupt();
72
71
  try {
73
- t.join();
72
+ thread.join();
74
73
  Log.d("MainActivity","thread join.");
75
74
  } catch (InterruptedException ignore) {
76
75
  }
76
+ thread = null;
77
77
  }
78
78
  }
79
79
 
80
- private class CountAction implements Runnable {
80
+ private class CountCallback implements Runnable {
81
81
  private int count;
82
+ CountCallback(int count) {
83
+ this.count = count;
84
+ }
85
+ @Override
82
86
  public void run() {
83
- count ++;
84
87
  textView.setText("count=" + count);
85
88
  Log.d("MainActivity","CountAction count="+count);
86
89
  }
87
90
  }
88
91
 
92
+ @Override
89
93
  public void run() {
94
+ Thread thisThread = Thread.currentThread();
90
- Log.d("MainActivity","run() start. "+Thread.currentThread());
95
+ Log.d("MainActivity","run() start. "+thisThread);
96
+ int count = 0;
97
+ for(boolean stop=false; !stop; ) {
91
- CountAction countAction = new CountAction();
98
+ CountCallback countCallback = new CountCallback(++count);
92
- while(thread != null) {
93
- mainHandler.removeCallbacks(countAction);
94
- mainHandler.post(countAction);
99
+ mainHandler.post(countCallback);
95
100
  try {
96
- thread.sleep(1000);
101
+ thisThread.sleep(1000);
97
- } catch (InterruptedException ignore) {
102
+ } catch (InterruptedException e) {
103
+ stop = true;
98
104
  }
105
+ mainHandler.removeCallbacks(countCallback); //念の為
99
106
  }
100
- mainHandler.removeCallbacks(countAction);
101
- Log.d("MainActivity","run() end. "+Thread.currentThread());
107
+ Log.d("MainActivity","run() stop. "+thisThread);
102
108
  }
103
109
  }
104
110
  ```

7

コード追加

2021/12/03 19:26

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -8,4 +8,97 @@
8
8
  start() / stop() メソッドはライフサイクルの onStart() / onStop() メソッドではありませんので、ご提示のコードでは全く実行されないですね。
9
9
  onStart()/ onStop() であれば(手元で実際に確認した所では)実機のスクリーンが off の状態で AndroidStudio で実行すると onStart() の後即 onStop() 実行されますので、 onStart でスレッドを開始し onStop でスレッドを停止させれば、スクリーン off 時はカウントが止まり、スクリーン on でまたカウントするようになると思います。
10
10
 
11
- スクリーン on でまた 0 からカウントするのであれば、 onStart で count = 0 してからスレッドを開始すれば良いかと思います。
11
+ スクリーン on でまた 0 からカウントするのであれば、 onStart で count = 0 してからスレッドを開始すれば良いかと思います。
12
+
13
+ ----
14
+ 次のようなコードにすれば、実行時のプログラムの動作が logcat に出ますので、画面を off にしてみたりして確認してみてください。
15
+ Handler で post するオブジェクトを remove できるように使い回すようにし、 count をそのオブジェクトに移動させることでスレッド再実行時にはまた最初からとなるようにしています。
16
+
17
+ (EmptyActivity から作ったプロジェクトで、 Hello World! を表示していた TextView に ```android:id="@+id/textView"``` を加えて使っています。)
18
+
19
+ ```java
20
+ package com.teratail.q372044;
21
+
22
+ import androidx.appcompat.app.AppCompatActivity;
23
+
24
+ import android.os.*;
25
+ import android.util.Log;
26
+ import android.widget.TextView;
27
+
28
+ public class MainActivity extends AppCompatActivity implements Runnable {
29
+ private Thread thread;
30
+ private Handler mainHandler = new Handler(Looper.getMainLooper());
31
+ private TextView textView;
32
+
33
+ @Override
34
+ protected void onCreate(Bundle savedInstanceState) {
35
+ super.onCreate(savedInstanceState);
36
+ setContentView(R.layout.activity_main);
37
+
38
+ textView = findViewById(R.id.textView);
39
+
40
+ start();
41
+ }
42
+
43
+ @Override
44
+ protected void onStart() {
45
+ Log.d("MainActivity","onStart()");
46
+ super.onStart();
47
+ start();
48
+ }
49
+
50
+ @Override
51
+ protected void onStop() {
52
+ Log.d("MainActivity","onStop()");
53
+ super.onStop();
54
+ stop();
55
+ }
56
+
57
+ public void start(){
58
+ Log.d("MainActivity","start()");
59
+ if(thread == null){
60
+ thread = new Thread(this);
61
+ Log.d("MainActivity","thread start.");
62
+ thread.start();
63
+ }
64
+ }
65
+
66
+ public void stop(){
67
+ Log.d("MainActivity","stop()");
68
+ if(thread != null) {
69
+ Thread t = thread;
70
+ thread = null;
71
+ t.interrupt();
72
+ try {
73
+ t.join();
74
+ Log.d("MainActivity","thread join.");
75
+ } catch (InterruptedException ignore) {
76
+ }
77
+ }
78
+ }
79
+
80
+ private class CountAction implements Runnable {
81
+ private int count;
82
+ public void run() {
83
+ count ++;
84
+ textView.setText("count=" + count);
85
+ Log.d("MainActivity","CountAction count="+count);
86
+ }
87
+ }
88
+
89
+ public void run() {
90
+ Log.d("MainActivity","run() start. "+Thread.currentThread());
91
+ CountAction countAction = new CountAction();
92
+ while(thread != null) {
93
+ mainHandler.removeCallbacks(countAction);
94
+ mainHandler.post(countAction);
95
+ try {
96
+ thread.sleep(1000);
97
+ } catch (InterruptedException ignore) {
98
+ }
99
+ }
100
+ mainHandler.removeCallbacks(countAction);
101
+ Log.d("MainActivity","run() end. "+Thread.currentThread());
102
+ }
103
+ }
104
+ ```

6

追加

2021/12/03 15:47

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -6,4 +6,6 @@
6
6
 
7
7
  少し勘違いしていました。すいません。
8
8
  start() / stop() メソッドはライフサイクルの onStart() / onStop() メソッドではありませんので、ご提示のコードでは全く実行されないですね。
9
- onStart()/ onStop() であれば(手元で実際に確認した所では)実機のスクリーンが off の状態で AndroidStudio で実行すると onStart() の後即 onStop() 実行されますので、 onStart でスレッドを開始し onStop でスレッドを停止させれば、スクリーン off 時はカウントが止まり、スクリーン on でまたカウントするようになると思います。
9
+ onStart()/ onStop() であれば(手元で実際に確認した所では)実機のスクリーンが off の状態で AndroidStudio で実行すると onStart() の後即 onStop() 実行されますので、 onStart でスレッドを開始し onStop でスレッドを停止させれば、スクリーン off 時はカウントが止まり、スクリーン on でまたカウントするようになると思います。
10
+
11
+ スクリーン on でまた 0 からカウントするのであれば、 onStart で count = 0 してからスレッドを開始すれば良いかと思います。

5

修正

2021/12/03 15:30

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -6,4 +6,4 @@
6
6
 
7
7
  少し勘違いしていました。すいません。
8
8
  start() / stop() メソッドはライフサイクルの onStart() / onStop() メソッドではありませんので、ご提示のコードでは全く実行されないですね。
9
- onStart()/ onStop() であれば(手元で実際に確認した所では)実機のスクリーンが off の状態で AndroidStudio で実行すると onStart() の後即 onStop() 実行されますので、 onStart でスレッドを開始し onStop でスレッドを停止させれば、スクリーン off 時はカウントが止まり、スクリーン on で最初からカウントするようになると思います。
9
+ onStart()/ onStop() であれば(手元で実際に確認した所では)実機のスクリーンが off の状態で AndroidStudio で実行すると onStart() の後即 onStop() 実行されますので、 onStart でスレッドを開始し onStop でスレッドを停止させれば、スクリーン off 時はカウントが止まり、スクリーン on でまたカウントするようになると思います。

4

勘違い修正

2021/12/03 15:28

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -4,8 +4,6 @@
4
4
  stop() での thread 変数の null 化の **後** に、スレッドに対して割り込みをかけて sleep を抜けさせ、 while (thread!=null) を通って停止するまで join して確実にスレッドを止まったことを確認したほうが良いのではないでしょうか。
5
5
  また、MainLoop に post した処理がまだ未処理で残っている場合もありますので、出来ればそれをキャンセルするべきかもしれませんが…現状ではそのオブジェクトは作りっぱなしですので修正が大変かもしれません。
6
6
 
7
- ----
8
- リーンOn/Off を検出する方法につきましては、
9
- [(Android)スクリーンのON/OFFを検出する](https://iyemon018.hatenablog.com/entry/2017/12/28/012030)
10
- という記事がありました。
11
- (4年前の記事なので今も出来るのかは分かりません。私はやったことがありませんので^^; )
7
+ 少し勘違いしていました。すいません。
8
+ start() / stop() メソッドはライフサイonStart() / onStop() メソッドでありませんのでご提示のコードでは全く実行されないですね。
9
+ onStart()/ onStop() であれば(手元で実際に確認した所では)実機のスクリーンが off 状態で AndroidStudio で実行すると onStart() の後即 onStop() 実行されますので、 onStart でスレッドを開始し onStop でスレッドを停止させれば、スクリーン off 時はカウントが止まり、スクリーン on で最初からカウントするようになると思います。

3

修正

2021/12/03 15:24

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -8,4 +8,4 @@
8
8
  スクリーンの On/Off を検出する方法につきましては、
9
9
  [(Android)スクリーンのON/OFFを検出する](https://iyemon018.hatenablog.com/entry/2017/12/28/012030)
10
10
  という記事がありました。
11
- (私はやったことがありません)
11
+ (4年前の記事なので今も出来るのかは分かりません。私はやったことがありませんので^^; )

2

追加

2021/12/03 10:23

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -2,4 +2,10 @@
2
2
 
3
3
  スレッドが停止していないということですね。
4
4
  stop() での thread 変数の null 化の **後** に、スレッドに対して割り込みをかけて sleep を抜けさせ、 while (thread!=null) を通って停止するまで join して確実にスレッドを止まったことを確認したほうが良いのではないでしょうか。
5
- また、MainLoop に post した処理がまだ未処理で残っている場合もありますので、出来ればそれをキャンセルするべきかもしれませんが…現状ではそのオブジェクトは作りっぱなしですので修正が大変かもしれません。
5
+ また、MainLoop に post した処理がまだ未処理で残っている場合もありますので、出来ればそれをキャンセルするべきかもしれませんが…現状ではそのオブジェクトは作りっぱなしですので修正が大変かもしれません。
6
+
7
+ ----
8
+ スクリーンの On/Off を検出する方法につきましては、
9
+ [(Android)スクリーンのON/OFFを検出する](https://iyemon018.hatenablog.com/entry/2017/12/28/012030)
10
+ という記事がありました。
11
+ (私はやったことがありません。)

1

誤字

2021/12/03 10:22

投稿

jimbe
jimbe

スコア13357

answer CHANGED
@@ -1,5 +1,5 @@
1
1
  > しばらくしてからスマホの電源を入れてアプリを表示させると、すでにcountがかなり進んだ状態で表示されます。
2
2
 
3
3
  スレッドが停止していないということですね。
4
- stop() での thread 変数の null 化の **後** に、スレッドに対して割り込みをけて sleep を抜けさせ、 while (thread!=null) を通って停止するまで join して確実にスレッドを止まったことを確認したほうが良いのではないでしょうか。
4
+ stop() での thread 変数の null 化の **後** に、スレッドに対して割り込みをけて sleep を抜けさせ、 while (thread!=null) を通って停止するまで join して確実にスレッドを止まったことを確認したほうが良いのではないでしょうか。
5
5
  また、MainLoop に post した処理がまだ未処理で残っている場合もありますので、出来ればそれをキャンセルするべきかもしれませんが…現状ではそのオブジェクトは作りっぱなしですので修正が大変かもしれません。