연습장/실습

Basic 4주차_ 1-2. 생명 주기(Lifecycle)

아이른 2024. 4. 15. 12:53

문제 1. 

  • 화면 회전시 랜덤변수 유지하기
  • 카운터가 100이 되었을 때 화면을 회전하면 1로 바뀌는 원인 찾은 후, 회전 하더라도 100으로 유지되도록 출력하기
  • 홈 화면으로 갔을 때 멈추고 돌아오면 이어서 실행하기
  • 버튼을 클릭하여 멈춘 경우, 어떤 상황에서도 재실행 되어서는 안되도록 하기

3. 버튼을 클릭하여 멈춘 경우, 값 유지 및 어떤 상황에서도 재실행 되어서는 안되도록 하기

  • 버튼을 누르면 멈춤 > 눌렀는지 안눌렀는지 상태를 저장 > 불러올 때 조건식을 통해 구분하여 진행
  • 클릭하였을 때의 처리를 하기 위한 변수 생성
class Basic3WeekActivity : AppCompatActivity() {
    private var isChecked = false
...
  • 눌렀는지 안눌렀는지 상태를 저장 
    • 버튼을 클릭하였을 때
    • 코루틴이 전부 돌아갔을 때
class Basic3WeekActivity : AppCompatActivity() {
    private var isChecked = false
...

    override fun onCreate(savedInstanceState: Bundle?) {
        binding = ActivityBasic3WeekBinding.inflate(layoutInflater)
        super.onCreate(savedInstanceState)
        Log.i(TAG, "onCreate")
        setContentView(binding.root)

        if (savedInstanceState != null) {
            randomValue = savedInstanceState.getInt("random")
            counter = savedInstanceState.getInt("counter")
            isChecked = savedInstanceState.getBoolean("isCheck")//값 받기
            
..

    private fun setupButton() { //버튼을 클릭하였을 때
        binding.clickButton.setOnClickListener {
            checkAnswerAndShowToast()
            job?.cancel()
            isChecked = true
        }
    }

...

    private fun setJobAndLaunch() { //카운터 100까지 다 돌아갔을 때
        job?.cancel()
        job = lifecycleScope.launch {
            if (!isChecked) {
                if (isActive) {
                    while (counter <= 100) {
                        binding.spartaTextView.text = counter++.toString()
                        delay(100)
                    }
                }
            }
        }
    }

...

    override fun onSaveInstanceState(outState: Bundle) {//값 전달
        super.onSaveInstanceState(outState)
        outState.putBoolean("isCheck", isChecked)
..
    }
    
..

 

3-1. 문제점

  • 로그를 살펴보았을 때, 문제는 없으나 화면 전환 시 변화없음
    • true일 때 화면에 보여지게 처리

...
override fun onCreate(savedInstanceState: Bundle?) {
    binding = ActivityBasic3WeekBinding.inflate(layoutInflater)
    super.onCreate(savedInstanceState)
    setContentView(binding.root)

    if (savedInstanceState != null) {
        randomValue = savedInstanceState.getInt("random")
        counter = savedInstanceState.getInt("counter")
        //onRestoreInstanceState 메서드에서 동작할 경우 초기화되기 때문에 onCreate이후에서만
        binding.spartaTextView.text = counter.toString()

        isChecked = savedInstanceState.getBoolean("isCheck")
...
  • 버튼을 누르고 화면 회전 시 값이 증가
    • 전위연산자의 개념 알고가기

 

fun main(){
   var counter = 0
   println(counter++)
}
/*출력
예상 : 1
실제 : 0
*/

fun main(){
   var counter = 0
   println(counter++)
   println(counter)//1
}//그 다음 카운터 변수를 사용할 때 적용

fun main(){
   var counter = 0
   println(counter)//0
   println(counter++)//0
   println(counter)//1
}
  • 버튼을 누르고 화면 회전 시 값 변동 없음
//사용 1.
private fun setJobAndLaunch() {
    job?.cancel()
    job = lifecycleScope.launch {
        if (!isChecked) {
            if (isActive) {
                while (counter <= 100) {
                    binding.spartaTextView.text = counter.toString()
                    delay(100)
                    counter += 1
                }
            }
        }
    }
}

//사용 2.
private fun setJobAndLaunch() {
    job?.cancel()
    job = lifecycleScope.launch {
        if (isActive) {
            while (counter <= 100) {
                binding.spartaTextView.text = counter.toString()
                if (isChecked == true) {
                    break
                    //job?.cancel()
                }
                delay(500)
                counter += 1
            }
        }
    }
}
  • 버튼을 누르지 않고 카운터가 100이 되어 화면 회전 시 값이 증가

 

4. 카운터가 100이 되었을 때 화면을 회전하면 1로 바뀌는 원인 찾은 후, 회전 하더라도 100으로 유지되도록 출력하기

  • 카운터 값이 변하지 않도록 유지
override fun onCreate(savedInstanceState: Bundle?) {
    binding = ActivityBasic3WeekBinding.inflate(layoutInflater)
    super.onCreate(savedInstanceState)
    Log.i(TAG, "onCreate")
    setContentView(binding.root)

    if (savedInstanceState != null) {
        randomValue = savedInstanceState.getInt("random")
        counter = savedInstanceState.getInt("counter")
        if (counter > 100){
            counter = 100
        }//카운터 값 유지
        binding.spartaTextView.text = counter.toString()

        isChecked = savedInstanceState.getBoolean("isCheck")
        if (isChecked == true){
            binding.spartaTextView.text = counter.toString()
        }//받은 카운터 값을 보여줌
    }

 

 

5. 홈 화면으로 갔을 때 멈추고 돌아오면 이어서 실행하기

  • 홈 화면으로 갔을 때 onPause상태였다가 이어서 실행하면 onRestart를 타서 onStart가 실행
    • onPause : job을 멈춤
    • onResume : 코루틴 구문 실행

더보기
  • 전체 코드(수정)
package com.example.basic1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.PersistableBundle
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.example.basic1.databinding.ActivityBasic3WeekBinding
import com.example.basic1.databinding.ActivityMainBinding
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch

class Basic3WeekActivity : AppCompatActivity() {

    private var randomValue = (1..100).random()
    private var job: Job? = null
    private lateinit var binding: ActivityBasic3WeekBinding
    private val TAG = "MainActivity"
    private var counter = 1
    private var isChecked = false

    override fun onCreate(savedInstanceState: Bundle?) {
        binding = ActivityBasic3WeekBinding.inflate(layoutInflater)
        super.onCreate(savedInstanceState)
        Log.i(TAG, "onCreate")
        setContentView(binding.root)

        if (savedInstanceState != null) {
            randomValue = savedInstanceState.getInt("random")
            isChecked = savedInstanceState.getBoolean("isCheck")
        }

        setupButton()
        setRandomValueBetweenOneToHundred()
    }

    override fun onRestart() {
        super.onRestart()
        Log.i(TAG, "onRestart")
    }

    override fun onResume() {
        super.onResume()
        Log.i(TAG, "onResume")
        setJobAndLaunch()
    }

    override fun onPause() {
        super.onPause()
        Log.i(TAG, "onPause")
        job?.cancel()
    }

    override fun onStop() {
        super.onStop()
        Log.i(TAG, "onStop")
    }

    override fun onStart() {
        super.onStart()
        Log.i(TAG, "onStart")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.i(TAG, "onDestroy")
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        Log.i(TAG, "onSaveInstanceState")
        outState.putInt("counter", counter)
        outState.putInt("random", randomValue)
        outState.putBoolean("isCheck", isChecked)
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        Log.i(TAG, "onRestoreInstanceState")
        counter = savedInstanceState.getInt("counter")
        if (counter > 100) {
            counter = 100
        }
    }

    private fun setupButton() {
        binding.clickButton.setOnClickListener {
            checkAnswerAndShowToast()
            job?.cancel()
            isChecked = true
        }
    }

    private fun setRandomValueBetweenOneToHundred() {
        binding.textViewRandom.text = randomValue.toString()
    }

    private fun setJobAndLaunch() {
        job?.cancel()
        job = lifecycleScope.launch {
            if (isActive) {
                while (counter <= 100) {
                    setSpartaTextView()
                    if (isChecked) {
                        break
                    }
                    delay(500)
                    counter += 1
                }
            }
        }
    }

    private fun checkAnswerAndShowToast() {
        val spartaText = binding.spartaTextView.text.toString()
        val randomText = binding.textViewRandom.text.toString()

        if (spartaText == randomText) {
            Toast.makeText(this, "Correct!", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, "Wrong!", Toast.LENGTH_SHORT).show()
        }
    }

    private fun setSpartaTextView() {
        binding.spartaTextView.text = counter.toString()
    }
}