
실습 팀은 다음주에 새로운 팀으로 구성 예정
실습 팀 리더가 따로 없었는데 다음부터는 팀 리더도 정할 예정임
1월 26일은 휴강, Coroutine 특강 예정 꼭 참여 필수!
1월 29일에 취업 관련 특강이 있을 예정(18시~20시)

어플리케이션 처음 실행 시
onCreate() -> onStart() -> onResume()
다른 activity 실행시 기존 activity는 onPause()
다른 activity화면이 기존 activity 화면보다 작을 경우에는 onResume()으로 되돌아감
다른 activity화면이 기존 activity화면을 전부 가릴 경우에는 onStop() 갔다가 다시 기존 activity로 갈 경우 onRestart()
onStop으로 가는 기준이 명확하지 않아 실제 개발에서는 onStart()와 onStop()은 잘 사용 안한다고 함(강사님 기준인지?)
안드로이드의 <-버튼은 실제로 뒤로가기 버튼이 아님, 현재 눈에 보이고 있는 activity를 종료시키는 버튼임
back stack
class MainActivity : AppCompatActivity() {
// Activity가 처음 실행될 때
// 화면 전환이 발생했을 때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("test1234","onCreate")
}
}
맨 처음 실행하면

로그캣에 onCreate 확인

화면을 회전시키면

로그캣에 onCreate가 또 호출된 것을 확인

package kr.co.lion.android25_activitylifecycle
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
class MainActivity : AppCompatActivity() {
// Activity가 처음 실행될 때
// 화면 전환이 발생했을 때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("test1234","onCreate")
}
// onStart
// Activity 동작이 실행될 때
// Stop 상태에서 다시 Start 상태가 될 때
override fun onStart() {
super.onStart()
Log.d("test1234","onStart")
}
// onResume
// Activity 동작이 다시 시작될 때
// Pause 상태에서 다시 Running 상태가 되기 전
override fun onResume() {
super.onResume()
Log.d("test1234", "onResume")
}
// onRestart
// Stop 상태에서 Start 상태가 되기 전에 호출된다.
override fun onRestart() {
super.onRestart()
Log.d("test1234","onRestart")
}
// onPause
// Running 상태에서 일시 정지가 될 때
override fun onPause() {
super.onPause()
Log.d("test1234","onPause")
}
// onStop
// Running 상태에서 정지가 될 때
override fun onStop() {
super.onStop()
Log.d("test1234","onStop")
}
// onDestroy
// Activity가 종료될 때
override fun onDestroy() {
super.onDestroy()
Log.d("test1234","onDestroy")
}
}
처음 어플을 실행시키면

홈화면으로 나가면

홈화면에서 다시 어플로 들어가면

뒤로가기 버튼으로 나가면

어플이 정상적으로 동작할때만 위의 메서드들이 동작하고, 오류가 발생하거나 비정상적으로 종료되는 경우(강제종료 등)에는 위의 메서드들이 동작하지 않음


Activity Name만 수정하고 나머지는 기본값으로 두기



// MainActivity.kt
package kr.co.lion.android26_startactivity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android26_startactivity.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
buttonStartSecond.setOnClickListener {
// Intent 객체
// Intent : 안드로이드 4대 구성요소를 실행하기 위해 OS에게 전달하는 요청 정보 객체
// 실행하고자 하는 것과 관련된 모든 정보들을 담아 OS로 전달하면 OS가 이를 보고 실행해준다.
// 두 번째 매개변수 : 실행하고자 하는 Activity의 자바 클래스를 지정한다.
val secondIntent = Intent(this@MainActivity, SecondActivity::class.java)
// Activity 실행
// Intent에 등록한 클래스를 확인하여 그 클래스의 객체를 생성하고 onCreate 메서드를 호출한다.
// 이 때 만들어진 화면이 보이게 된다.
startActivity(secondIntent)
}
}
}
}
// SecondActivity.kt
package kr.co.lion.android26_startactivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android26_startactivity.databinding.ActivitySecondBinding
class SecondActivity : AppCompatActivity() {
// activity_second.xml로 생성했기 때문에 ActivitySecondBinding 클래스
lateinit var activitySecondBinding: ActivitySecondBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activitySecondBinding = ActivitySecondBinding.inflate(layoutInflater)
setContentView(activitySecondBinding.root)
activitySecondBinding.apply {
buttonFinishSecond.setOnClickListener {
// 현재 Activity를 종료한다.
// Activity가 종료되면 BackStack에서 Activity가 제거되고
// 메모리에서도 제거된다(완전 제거)
finish()
}
}
}
}


안드로이드에서 이전으로 돌아가는 개념은 없다
현재 activity를 종료시키는 것
크롬 어플에서 뒤로가기 버튼을 누르면 이전페이지로 이동하도록 개발자가 오버라이딩 해놓은 것임

// MainActivity.kt
...
activityMainBinding.apply {
buttonStartSecond.setOnClickListener {
// Intent 객체
// Intent : 안드로이드 4대 구성요소를 실행하기 위해 OS에게 전달하는 요청 정보 객체
// 실행하고자 하는 것과 관련된 모든 정보들을 담아 OS로 전달하면 OS가 이를 보고 실행해준다.
// 두 번째 매개변수 : 실행하고자 하는 Activity의 자바 클래스를 지정한다.
val secondIntent = Intent(this@MainActivity, SecondActivity::class.java)
// 새롭게 실행되는 Activity에 전달할 데이터가 있다면 Intent에 담아준다.
secondIntent.putExtra("data1",100)
secondIntent.putExtra("data2",11.11)
secondIntent.putExtra("data3",true)
// Activity 실행
// Intent에 등록한 클래스를 확인하여 그 클래스의 객체를 생성하고 onCreate 메서드를 호출한다.
// 이 때 만들어진 화면이 보이게 된다.
startActivity(secondIntent)
}
}
...
// SecondActivity.kt
...
activitySecondBinding.apply {
// Acitivity를 실행하기 위해 사용한 Intent는 실행된 Activity까지 전달된다.
// Intent를 통해 전달된 데이터를 출력한다.
textViewSecond.apply {
// Intent에 담겨서 전달된 데이터를 가져온다.
val data1 = intent?.getIntExtra("data1",0)
val data2 = intent?.getDoubleExtra("data2",0.0)
val data3 = intent?.getBooleanExtra("data3",false)
text = "SecondActivity\n"
append("data1 : ${data1}\n")
append("data2 : ${data2}\n")
append("data3 : $data3")
}
...


// MainActivity.kt
package kr.co.lion.android26_startactivity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android26_startactivity.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
buttonStartThird.setOnClickListener {
val thirdIntent = Intent(this@MainActivity, ThirdActivity::class.java)
thirdIntent.putExtra("data1",200)
thirdIntent.putExtra("data2",22.22)
thirdIntent.putExtra("data3",true)
// 다른 액티비티를 실행시키고 돌아왔을 때 받을 데이터가 없다면
// startActivity로 실행한다.
// 만약 돌아올 때 전달받을 데이터가 있다면
// 두 번째 정수 값 : requestCode라고 부른다. 돌아왔을 때 이 값이 그대로 전달된다.
// requestCode는 어떤 Activity를 실행했다가 돌아왔는지를 구분하기 위해 사용한다.
startActivityForResult(thirdIntent, 1000)
}
}
}
// startActivityForResult 메서드를 통해 다른 Activity를 실행하고 돌아왔을 때 자동으로 호출되는 메서드
// 첫 번째 매개변수 : startActivityForResult 메서드 호출 시 넣어준 두 번째 매개 변수의 값
// 이것을 통해 어떤 Activity를 갔다 왔는지 확인한다.
// 두 번째 매개변수 : 새롭게 실행된 Activity에서 Activity 종료 전에 setResult 메서드를 통해 설정한 결과 값이 들어온다.
// 실행되었던 Activity에서의 작업의 결과를 구분하는 용도로 사용한다.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// requestCode(어떤 Activity를 갔다 왔는가)로 분기한다.
when(requestCode){
1000 -> {
// resultCode(실행되었던 Activity의 작업의 결과)에 따라 분기한다.
when(resultCode){
RESULT_OK -> activityMainBinding.textViewMain.text = "작업이 잘 끝났습니다."
RESULT_CANCELED -> activityMainBinding.textViewMain.text = "작업이 취소되었습니다."
RESULT_FIRST_USER -> activityMainBinding.textViewMain.text = "작업의 결과가 사용자 정의 1이 되었습니다"
RESULT_FIRST_USER + 1 -> activityMainBinding.textViewMain.text = "작업의 결과가 사용자 정의 2이 되었습니다"
RESULT_FIRST_USER + 2 -> activityMainBinding.textViewMain.text = "작업의 결과가 사용자 정의 3이 되었습니다"
}
}
}
}
}
// ThirdActivity.kt
package kr.co.lion.android26_startactivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android26_startactivity.databinding.ActivityThirdBinding
class ThirdActivity : AppCompatActivity() {
lateinit var activityThirdBinding: ActivityThirdBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityThirdBinding = ActivityThirdBinding.inflate(layoutInflater)
setContentView(activityThirdBinding.root)
activityThirdBinding.apply {
textViewThird.apply {
// Intent에 담겨서 전달된 데이터를 가져온다.
val data1 = intent?.getIntExtra("data1",0)
val data2 = intent?.getDoubleExtra("data2",0.0)
val data3 = intent?.getBooleanExtra("data3",false)
text = "ThirdActivity\n"
append("data1 : ${data1}\n")
append("data2 : ${data2}\n")
append("data3 : $data3")
}
buttonFinishThird.setOnClickListener {
// 현재 Activity가 종료되고 이전 Activity가 다시 실행될 때
// 현재 Activity의 작업의 결과를 이전 Activity가 알 수 있도록 설정해준다.
// RESULT_OK : 작업이 잘 되었다는 의미로 사용한다.
// RESULT_CANCELED : 작업이 취소되었다는 의미로 사용한다. 사용자가 Back Button을 누르면 이 값이 설정된다.
// RESULT_FIRST_USER : 그 외의 결과를 정의할 때 사용한다. +1, +2, +3 식으로 해서 다양한 결과를 정의한다.
setResult(RESULT_OK)
finish()
}
}
}
}


Third Activity 종료 버튼을 누르면 RESULT_OK가 전달됨

버튼을 누르지 않고 뒤로가기 버튼을 누르면 RESULT_CANCELED가 전달됨

굳이 RESULT_OK나 RESULT_CANCELED를 사용할 필요없이 정수값을 사용해도 된다.
// MainActivity.kt
package kr.co.lion.android26_startactivity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android26_startactivity.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
activityMainBinding.apply {
buttonStartThird.setOnClickListener {
val thirdIntent = Intent(this@MainActivity, ThirdActivity::class.java)
thirdIntent.putExtra("data1",200)
thirdIntent.putExtra("data2",22.22)
thirdIntent.putExtra("data3",true)
// 다른 액티비티를 실행시키고 돌아왔을 때 받을 데이터가 없다면
// startActivity로 실행한다.
// 만약 돌아올 때 전달받을 데이터가 있다면
// 두 번째 정수 값 : requestCode라고 부른다. 돌아왔을 때 이 값이 그대로 전달된다.
// requestCode는 어떤 Activity를 실행했다가 돌아왔는지를 구분하기 위해 사용한다.
startActivityForResult(thirdIntent, 1000)
}
}
}
// startActivityForResult 메서드를 통해 다른 Activity를 실행하고 돌아왔을 때 자동으로 호출되는 메서드
// 첫 번째 매개변수 : startActivityForResult 메서드 호출 시 넣어준 두 번째 매개 변수의 값
// 이것을 통해 어떤 Activity를 갔다 왔는지 확인한다.
// 두 번째 매개변수 : 새롭게 실행된 Activity에서 Activity 종료 전에 setResult 메서드를 통해 설정한 결과 값이 들어온다.
// 실행되었던 Activity에서의 작업의 결과를 구분하는 용도로 사용한다.
// 세 번째 매개변수 : 새롭게 실행된 Activity에서 setResult 메서드에 설정된 Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// requestCode(어떤 Activity를 갔다 왔는가)로 분기한다.
when(requestCode){
1000 -> {
// resultCode(실행되었던 Activity의 작업의 결과)에 따라 분기한다.
when(resultCode){
RESULT_OK -> {
activityMainBinding.textViewMain.text = "작업이 잘 끝났습니다.\n"
if(data != null){
val value1 = data.getIntExtra("value1",0)
val value2 = data.getDoubleExtra("value2",0.0)
val value3 = data.getBooleanExtra("value3",false)
activityMainBinding.textViewMain.append("value1 : ${value1}\n")
activityMainBinding.textViewMain.append("value2 : ${value2}\n")
activityMainBinding.textViewMain.append("value3 : ${value3}\n")
}
}
RESULT_CANCELED -> activityMainBinding.textViewMain.text = "작업이 취소되었습니다."
RESULT_FIRST_USER -> activityMainBinding.textViewMain.text = "작업의 결과가 사용자 정의 1이 되었습니다"
RESULT_FIRST_USER + 1 -> activityMainBinding.textViewMain.text = "작업의 결과가 사용자 정의 2이 되었습니다"
RESULT_FIRST_USER + 2 -> activityMainBinding.textViewMain.text = "작업의 결과가 사용자 정의 3이 되었습니다"
}
}
}
}
}
// ThirdActivity.kt
package kr.co.lion.android26_startactivity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kr.co.lion.android26_startactivity.databinding.ActivityThirdBinding
class ThirdActivity : AppCompatActivity() {
lateinit var activityThirdBinding: ActivityThirdBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityThirdBinding = ActivityThirdBinding.inflate(layoutInflater)
setContentView(activityThirdBinding.root)
activityThirdBinding.apply {
textViewThird.apply {
// Intent에 담겨서 전달된 데이터를 가져온다.
val data1 = intent?.getIntExtra("data1",0)
val data2 = intent?.getDoubleExtra("data2",0.0)
val data3 = intent?.getBooleanExtra("data3",false)
text = "ThirdActivity\n"
append("data1 : ${data1}\n")
append("data2 : ${data2}\n")
append("data3 : $data3")
}
buttonFinishThird.setOnClickListener {
// 현재 Activity가 종료되고 이전 Activity가 다시 실행될 때
// 현재 Activity의 작업의 결과를 이전 Activity가 알 수 있도록 설정해준다.
// RESULT_OK : 작업이 잘 되었다는 의미로 사용한다.
// RESULT_CANCELED : 작업이 취소되었다는 의미로 사용한다. 사용자가 Back Button을 누르면 이 값이 설정된다.
// RESULT_FIRST_USER : 그 외의 결과를 정의할 때 사용한다. +1, +2, +3 식으로 해서 다양한 결과를 정의한다.
// setResult(RESULT_OK)
// 이전 Activity로 전달되는 Intent
val resultIntent = Intent()
resultIntent.putExtra("value1",300)
resultIntent.putExtra("value2",33.33)
resultIntent.putExtra("value3",true)
// 작업의 결과를 설정할 때 Intent도 설정해주면 이전 Activity로 전달된다.
setResult(RESULT_OK,resultIntent)
finish()
}
}
}
}



// MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding.root)
// 계약 객체
// 다른 Activity를 갔다가 돌아왔을 때의 계약
val contract = ActivityResultContracts.StartActivityForResult()
// 계약을 등록한다.
// 다른 Activity를 갔다가 돌아오면 { } 내의 코드가 동작한다.
val fourthActivityLauncher = registerForActivityResult(contract){
// FourthActivity를 갔다 돌아왔을 때 동작할 코드를 작성한다.
activityMainBinding.textViewMain.text = "FourthActivity를 갔다 돌아왔습니다.\n"
if(it != null){
// 작업의 결과로 분기한다.
when(it.resultCode){
RESULT_OK -> {
// setResult 메서드에 설정한 Intent 객체로부터 데이터를 추출한다.
if(it.data != null){
val value1 = it?.data!!.getIntExtra("value1",0)
val value2 = it?.data!!.getDoubleExtra("value1",0.0)
val value3 = it?.data!!.getBooleanExtra("value1",false)
activityMainBinding.textViewMain.append("value1 : ${value1}\n")
activityMainBinding.textViewMain.append("value2 : ${value2}\n")
activityMainBinding.textViewMain.append("value3 : ${value3}\n")
}
}
RESULT_CANCELED -> activityMainBinding.textViewMain.text = "작업이 취소 되었습니다."
}
}
}
activityMainBinding.apply {
buttonStartFourth.setOnClickListener {
// Activity 실행
val fourthIntent = Intent(this@MainActivity, FourthActivity::class.java)
fourthIntent.putExtra("data1",500)
fourthIntent.putExtra("data2",55.55)
fourthIntent.putExtra("data3",true)
fourthActivityLauncher.launch(fourthIntent)
}
}
}
}
// FourthActivity.kt
class FourthActivity : AppCompatActivity() {
lateinit var activityFourthBinding: ActivityFourthBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityFourthBinding = ActivityFourthBinding.inflate(layoutInflater)
setContentView(activityFourthBinding.root)
activityFourthBinding.apply {
textViewFourth.apply {
// Intent에 담겨서 전달된 데이터를 가져온다.
val data1 = intent?.getIntExtra("data1",0)
val data2 = intent?.getDoubleExtra("data2",0.0)
val data3 = intent?.getBooleanExtra("data3",false)
text = "FourthActivity\n"
append("data1 : ${data1}\n")
append("data2 : ${data2}\n")
append("data3 : $data3")
}
buttonFinishFourth.setOnClickListener {
val resultIntent = Intent()
resultIntent.putExtra("value1",300)
resultIntent.putExtra("value2",33.33)
resultIntent.putExtra("value3",true)
// 작업의 결과를 설정할 때 Intent도 설정해주면 이전 Activity로 전달된다.
setResult(RESULT_OK,resultIntent)
finish()
}
}
}
}







※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스