마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 스레드 관련 질문

0 추천

앱을 돌리면 시작과 동시에 이미지들이 랜덤 배열돼서 끊임없이 움직이고 해당 이미지를 누르면 score가 1씩 증가하도록 하였습니다. 그리고 타이머 기능을 추가했는데 앱을 돌리면 타이머는 잘 작동되는데 이미지가 안나오네요 ..  어떤 부분을 수정봐야 할지 모르겠어서 이렇게 질문 드립니다.. 
 그리고 아예 해당 부분을 타이머 시작 버튼을 누르면 이미지 출력되도록 하고 싶어  startTimer() 안으로 넣어보려고 수정했는데 더 오류가 커져서 ;; 일단은 이렇게 뒀습니다 ㅠ 작성한 java코드입니다. (full코드는 용량 때문에 댓글로 달았습니다 )

public class MainActivity extends AppCompatActivity {
    ArrayList<Point> list;   //Point pos;
    int score = 0; 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
mButtonStart.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if(mTimerRunning) {
            pauseTimer();
        } else {
            startTimer();
        }
    }
});
class MyView extends View {
        public MyView(Context context) {
            super(context);
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    while (score <= 20) {
                        SystemClock.sleep(2000);
                        invalidate();
                    }
                }
            }.start();
        }//MyView()

        @Override
        public void draw(Canvas canvas) {
            super.draw(canvas);
            Paint paint = new Paint();
            paint.setTextSize(100);
            paint.setColor(Color.rgb(100, 100, 0));

            DisplayMetrics metrics = getResources().getDisplayMetrics();
            int dWidth = metrics.widthPixels;
            int dHeight = metrics.heightPixels;  //note

            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.donut2);
            bitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);

            Random random = new Random();
            list = new ArrayList<>();

            for (int i = 0; i < 10; i++) {
                Point pos = new Point(random.nextInt(dWidth), random.nextInt(dHeight));
                list.add(pos);
            }

            canvas.drawText("score: " + score, 100, 100, paint);
            for (Point pos : list)
                canvas.drawBitmap(bitmap, pos.x, pos.y, paint);


        }//draw()

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    for (Point pos : list) {
                        if ((event.getX() >= pos.x && event.getX() <= pos.x + 200)
                                && (event.getY() >= pos.y && event.getY() <= pos.y + 200)) {
                            score++;
                        }
                    }
                    break;
                default:
                    break;
            }
            return true;
        }//onTouchEvent()
    }
}
희망을기억해 (200 포인트) 님이 2022년 5월 27일 질문
<MainActivity.java>

public class MainActivity extends AppCompatActivity {
    ArrayList<Point> list;   //Point pos;
    int score = 0;
    private static final long START_TIME_IN_MILES = 600000;
    private TextView mTextViewCountDown;
    private Button mButtonStart;
    private Button mButtonReset;

    private CountDownTimer mCountDownTimer;
    private boolean mTimerRunning;
    private long mTimeLeftInMillis = START_TIME_IN_MILES;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextViewCountDown = findViewById(R.id.text_view_countdown);
        mButtonStart = findViewById(R.id.button_start);
        mButtonReset = findViewById(R.id.button_reset);

        mButtonStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mTimerRunning) {
                    pauseTimer();
                } else {
                    startTimer();
                }
            }
        });

        mButtonReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resetTimer();
            }
        });
        updateCountDownText();

        class MyView extends View {
            public MyView(Context context) {
                super(context);
                new Thread() {
                    @Override
                    public void run() {
                        super.run();
                        while (score <= 20) {
                            SystemClock.sleep(2000);
                            invalidate();
                        }
                    }
                }.start();
            }//MyView()

            @Override
            public void draw(Canvas canvas) {
                super.draw(canvas);
                Paint paint = new Paint();
                paint.setTextSize(100);
                paint.setColor(Color.rgb(100, 100, 0));

                DisplayMetrics metrics = getResources().getDisplayMetrics();
                int dWidth = metrics.widthPixels;
                int dHeight = metrics.heightPixels;  //note

                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.donut2);
                bitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);

                Random random = new Random();
                list = new ArrayList<>();

                for (int i = 0; i < 10; i++) {
                    Point pos = new Point(random.nextInt(dWidth), random.nextInt(dHeight));
                    list.add(pos);
                }

                canvas.drawText("score: " + score, 100, 100, paint);
                for (Point pos : list)
                    canvas.drawBitmap(bitmap, pos.x, pos.y, paint);


            }//draw()

            @Override
            public boolean onTouchEvent(MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        for (Point pos : list) {
                            if ((event.getX() >= pos.x && event.getX() <= pos.x + 200)
                                    && (event.getY() >= pos.y && event.getY() <= pos.y + 200)) {
                                score++;
                            }
                        }
                        break;
                    default:
                        break;
                }
                return true;
            }//onTouchEvent()
        }
    }

    private void startTimer() {
        mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                mTimeLeftInMillis = millisUntilFinished;
                updateCountDownText();
            }

            @Override
            public void onFinish() {
                mTimerRunning = false;
                mButtonStart.setText("시작");
                mButtonStart.setVisibility(View.INVISIBLE);
                mButtonReset.setVisibility(View.VISIBLE);
            }
        }.start();
        mTimerRunning = true;
        mButtonStart.setText("멈춤");
        mButtonReset.setVisibility(View.INVISIBLE);
    }
    private void pauseTimer() {
        mCountDownTimer.cancel();
        mTimerRunning = false;
        mButtonStart.setText("시작");
        mButtonReset.setVisibility(View.VISIBLE);
    }
    private void resetTimer() {
        mTimeLeftInMillis = START_TIME_IN_MILES;
        updateCountDownText();
        mButtonReset.setVisibility(View.INVISIBLE);
        mButtonStart.setVisibility(View.VISIBLE);
    }
    private void updateCountDownText() {
        int minutes = (int) (mTimeLeftInMillis / 1000) / 600;
        int seconds = (int) (mTimeLeftInMillis / 1000) % 60;

        String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);

        mTextViewCountDown.setText(timeLeftFormatted);
    }
}

1개의 답변

0 추천
new Thread() {
                    @Override
                    public void run() {
                        super.run();
                        while (score <= 20) {
                            SystemClock.sleep(2000); //<-- 요기
                            invalidate();
                        }
                    }
                }.start();

위처럼 쓰레드안에서 SystemClock.sleep(2000) 주시면 UI가 2초등안 block을 당할 것 같네요. 더군다나 SystemClock.sleep은 exception을 던지지 않아 메모리누수나 쓰레드interuption 등도 주의 깊게 체크해 보셔야 할 것 같네요.

주기적인 동작을 하는 코드는 경우 안드로이드에는 많은 옵션이 있습니다.

Timer, CountdownTimer, WorkManager, Alaramanager, Thread.wait() + Thread.notify(), Handler 등등
제일 적합한 걸 잘 검토하셔셔 선택하시길 바랍니다.

spark (227,830 포인트) 님이 2022년 5월 27일 답변
...