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

메인액티비티 종료시 메인액티비티에속한 surfaceView의 스레드 동작 모두 종료하는 법

0 추천
안녕하세요.

AsyncTask에서 액티비티 종료시 커스텀뷰의 surfaceView의 동작과 스레드를 모두 종료하는 방법 문의합니다.

코드가 복잡하게 되었는데

1. 메인액티비티로 aSyncTask를 쓰고 거기서 프로그래스바가 0 이 될때 startActivity 를 써서 다음 액티비티로 넘어가려고한다 .

2. thread에서는 이미지를 랜덤한 위치에 만들고 이동하는 기능을 수행합니다.

3. 액티비티를 종료할때 모든 스레드를 종료하고 다음 액티비티에서 에러가 안뜨게 하고 싶은데

   스레드가 바로 죽지 않아서 랜덤한 확률로 다음 액티비티로 넘어갈때 에러가 뜨면서 앱이 꺼집니다.

4. 메인액티비티에서 thread를 시작하지 않고 surfaceView를 사용하는 커스텀뷰에서 start를 시작해서

    메인액티비티에서 thread를 제어할 방법을 찾지 못했습니다 ,

5. 게임 방식은 터치하면 이미지가 사라지고 surfaceView에서 점수를 받아서 점수를 올릴 계획입니다 .

6. surfaceView는 메인 액티비티에서 xml에 커스텀뷰로 생성되며 thread의 생성자를 담고있습니다.

 

앱 구조는 이 설명과 같습니다 .

요약하면 프로그래스바 가   0 이 될때 액티비티를 종료하는데 커스텀뷰의 스레드가 바로 꺼지지 않아

  다음 액티비티에서 오류를 불러일으킨다.  동시에 처리해서 종료하는 방법을 모르겠습니다.

입니다.

아래는 제 소스 일부 입니다.

-- Main Activity

public class BubbleGame extends AppCompatActivity {

...

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

      ...

     

          ...
            //프로그래스바
            bar_BubbleGame.setProgress(bar_BubbleGame.getMax());
            txt_Bubble_score.setText("Score : " + T_score);
            txt_Bubble_score.setTextSize(20);
            startTime = System.currentTimeMillis();
            // asyncTask 실행
            new BubbleProgressTask().execute(bar_BubbleGame.getProgress())
    }

    class BubbleProgressTask extends AsyncTask<Integer, Integer, Boolean> {
        private boolean isPerformed = false;
        private boolean isCancelled = false;
        boolean bubbleRun = true;

        @Override
        protected Boolean doInBackground(Integer... params) {

            for (int i = params[0]; i >= 0; i--) {
                publishProgress(i);
                SystemClock.sleep(100);
            }
            if (isCancelled) {
                return isCancelled;
            }
            timeTakenMillis = System.currentTimeMillis() - startTime;
         
            return isPerformed;
        }

      

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            bar_BubbleGame.setProgress(values[0]);
            if (bar_BubbleGame.getProgress() > 0) {
                BubbleScore = mBubbleGameView.getBubbleScore();
                if (BubbleScore != 0) {
                    T_score += BubbleScore;
                    updateScore();
                }
            } else if (bar_BubbleGame.getProgress() == 0) {
                isPerformed = true;
            }
        }

       

        @Override
        protected void onPostExecute(Boolean performed) {
            super.onPostExecute(performed);
            if (performed) {
                // mBubbleGameView.setVisibility(View.GONE);
                // SystemClock.sleep(2000);
                PlayNextGame();
            }
        }
    }

    private void updateScore() {
        txt_Bubble_score.setText("Score : " + T_score);
    }

    private void PlayNextGame() {
    ...

        startActivity(intent);
        finish();
    }
}

 

-- SurfaceView 클래스( 스레드 시작 )

public class BubbleGameView extends SurfaceView implements SurfaceHolder.Callback {
   ...

    public void setBubbleScore(int bubbleScore) {
        BubbleScore = bubbleScore;
    }

    public BubbleGameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        mHolder = holder;
        mThread = new GameThread(holder, context);
        setFocusable(true);  // View가 포커스를 받을 수 있도록 설정
    }

    //-------------------------------------
    //  SurfaceView가 생성될 때 실행되는 부분
    //-------------------------------------
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mThread.setRunning(true);
        mThread.setDaemon(true);
        setFocusable(true);
        mThread.start();
       // MakeBubble();
    }

    //-------------------------------------
    //  SurfaceView가 해제될 때 실행되는 부분
    //-------------------------------------
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean done = true;
        mThread.setRunning(false);
        while (done) {
            try {
                mThread.join();                        // 스레드가 현재 step을 끝낼 때 까지 대기
                done = false;
            } catch (InterruptedException e) {  // 인터럽트 신호가 오면?
                // 그 신호 무시 - 아무것도 않음
            }
        } // while
        setFocusable(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // return super.onTouchEvent(event);
        BubbleScore = 0;
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            synchronized (mHolder) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                mThread.TouchBubble(x, y);
                // mThread.MakeBubble(x, y);
                BubbleScore += 100;
                setBubbleScore(BubbleScore);
            }
        } else {
            return false;
        }
        return true;

    }

}

 

-- Gamethread  run할때마다 이미지 생성

public class GameThread extends Thread {

    ...

     ...

        //-------------------------------------
        //  Canvas에 그리기
        //-------------------------------------
        public void run() {
            // while (!Thread.currentThread().isInterrupted()) {
            bubbleRun = getBubbleRun();
            while (bubbleRun) {
                bubbleRun = getBubbleRun();
                Canvas canvas = null;      // canvas를 만든다
                canvas = mHolder.lockCanvas();  // canvas를 잠그고 버퍼 할당
                boolean BubbleTurn  = true;
                try {
                    synchronized (mHolder) {  // 동기화 유지
                     if(BubbleTurn) {
                            MakeBubble();
                        }
                        BubbleTurn = !BubbleTurn;
                        MoveBubble();
                        canvas.drawBitmap(imgBack, 0, 0, null);
                        // 큰 비눗방울
                        for (Bubble tmp : mBubble) {
                            canvas.drawBitmap(tmp.imgBall, tmp.x - tmp.radi,  tmp.y - tmp.radi, null);
                        }
                        // 작은비눗방울
                        for (SmallBubble tmp : sBubble) {
                            canvas.drawBitmap(tmp.imgBall, tmp.x - tmp.radi,  tmp.y - tmp.radi, null);
                        }
                    } // sync
                } finally {       // 버퍼 작업이 끝나면
                    if (canvas != null)    // 버퍼의 내용을 View에 전송
                        mHolder.unlockCanvasAndPost(canvas);
                }
            } // while
        } // run

    }

- 메인액티비티의 xml 파일

<FrameLayout
    android:id="@+id/frame1"
   ....>

    <LinearLayout
        android:id="@+id/linear_text"
  ...
        >

        <TextView
            android:id="@+id/txt_Bubble_score"
          ...
            android:text="Score : "/>
    </LinearLayout>
   

    <LinearLayout
        android:id="@+id/linear_1"
    ...
        android:orientation="vertical"
      
        >

        <ProgressBar
            android:id="@+id/bar_BubbleGame"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:max="100"/>
    </LinearLayout>

  <seveno.android.miniseconds.BubbleShooter.BubbleGameView
        android:id="@+id/mBubbleGameView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>
골든레미 (250 포인트) 님이 2017년 8월 19일 질문

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...