사용자를 위한 UI 구성을 위해서는 화면을 그려야 하는데 이를 위해서 Activity컴포넌트를 사용합니다. 도화지 위에 그림을 그린다고 생각하면 Activity는 도화지라고 볼 수 있는 것입니다.
1. Activity 생성
기본적으로 제공되는 Activity 외에 새로운 Activity를 추가하여 사용자에게 필요한 다른 화면을 보여줄 수 있습니다. Activity를 추가하려면 먼저 Android Studio에서 Project -> app폴더에서 마우스 오른쪽 버튼을 눌러 New -> Activity -> Empty Activity를 선택합니다.
그러면 생성할 Activity를 설정하는 화면이 나오는데 여기서 Activity Name과 Layout Name은 원하는 이름으로 지정해 주면 됩니다. 다만 Activity Name은 새로운 단어마다 첫 글자를 대문자로 작성하며 Layout Name은 전부 소문자 하되 단어 사이에 _(언더바) 문자를 사용해 구분합니다.
Launcher Activity는 App실행 시 가장 먼저 실행하겠다는 의미로 일단 체크하지 않습니다. Package name은 Activity가 위치할 패키지인데 이 부분은 특별한 경우가 아니면 거의 수정하지 않습니다. Source Language는 Kotlin으로 하고 Target Source Set은 main으로 잡은 뒤 Finish를 눌러줍니다.
MyActivity라는 새로운 Activity가 추가되었습니다. 새로 추가한 Acitivy에 원하는 위젯을 임의로 배치합니다. 여기서는 Activity에 TextView하나를 추가하도록 하겠습니다.
그리고 본래 Activity인 MainActivity로 돌아와 아래와 같이 버튼 하나를 추가합니다.
그리고 MainActivity의 소스 편집기로 들어와 onCreate안에서 다음과 같이 코드를 작성합니다.
val intent = Intent(this, MyActivity::class.java)
Android에서 어떠한 Activity를 실행하려면 Activity를 실행하는 메서드(startActivity())를 호출해야 하는데 이때 어떤 Activity를 실행할지를 지정해야 합니다. 이를 위해 Activity를 인텐트에 담아놓고 인텐트를 필요한 메서드에 전달하여 Activity를 실행하는 형태로 진행됩니다.
이제 버튼을 클릭했을때 추가한 Activity를 호출하기 위해서 버튼의 리스너를 추가하고
button.setOnClickListener({
startActivity(intent)
})
App을 실행시켜 버튼을 클릭해 제대로 추가한 Activity를 호출하는지를 확인해 봅니다.
2. Activity 사이의 데이터 전달
위에서 다른 Activity를 호출할 때 intent를 사용했는데 이를 이용해서 필요한 데이터를 다른 Ativity로 전달할 수 있습니다. 이를 확인해 보기 위해 아래와 같이 intent에서 값을 넣는 putExtra함수를 추가합니다.
putEx... 까지만 입력하면 사용 가능한 함수 목록이 나오게 되는데 보시는 바와 같이 key(name)와 값(value)을 쌍으로 데이터를 추가할 수 있으며 다양한 형식의 값을 다룰 수 있습니다.
val intent = Intent(this, MyActivity::class.java)
intent.putExtra("myValue1", "abc")
intent.putExtra("myValue2", 123)
위와 같이 필요한 값을 추가하고 나면 값을 받아야 할 Activity에서는 다음과 같은 방법으로 값을 전달받을 수 있습니다.
textView.text = intent.getStringExtra("myValue1")
위 코드를 조금전 새롭게 추가한 MyActivity의 onCreate 메서드 안에 작성합니다. intent자체는 이미 Activity가 호출될 때 전달되는 것이므로 별다른 선언 없이 곧장 사용할 수 있으며 getStringExtra함수를 통해 문자열 형태의 값을 받도록 합니다.
myValue1 키값의 데이터는 어차피 문자열이므로 위와 같이 하면 정상적으로 동작하지만 동일한 함수로 myValue2를 지정하면 값을 받아올 수 없습니다. getStringExtra는 문자열을 받아오는 것이고 myValue2의 값은 정수형 데이터이므로 타입이 맞지 않기 때문입니다. 이 말은 가져오려는 데이터 타입에 따라서 값을 가져오는 함수 또한 다르게 써야 한다는 것을 의미합니다.
textView.text = "${intent.getIntExtra("myValue2", 0)}"
정수 형태의 값을 가져오기 위해 getIntExtra함수를 사용했습니다. 우선 getIntExtra 함수는 2개의 매개변수를 가져야 하는데 첫 번째는 가져오려는 값의 키값이고 두 번째는 아무런 값도 가져오지 못한 경우 사용되는 기본값입니다.
또한 함수전체를 ${}로 감싸 놓았는데 이는 값을 표시할 textView위젯의 text속성이 문자열 형태의 값만을 받는 것이므로 값이 문자열로 전달될 수 있도록 하기 위함입니다.
위와 같이 다른 Activity에서 값을 전달받으면 역으로 자신을 호출했던 Activity에 값을 되돌려 줘야 하는 경우도 있을 것입니다. 이때도 동일하게 Intent를 통해서 값을 저장하고 받을 수 있습니다. 이런 상황의 테스트를 위해 조금 변태 같지만 추가한 Activity의 textView위젯을 클릭했을 때 자신을 닫고 intent를 통해 값을 되돌려 줄 수 있도록 textView의 클릭 리스너를 작성합니다.
textView.setOnClickListener{
val intent = Intent()
}
다른 Activity를 호출하는 경우 Intent에 어떤 Activity를 호출할 것인지를 지정했지만 Activity를 종료하고 되돌려 주는 경우에는 대상을 특정할 필요가 없기에 Intent() 까지만 작성합니다.
textView.setOnClickListener{
val intent = Intent()
intent.putExtra("myValue3", "반환값")
}
역시 동일한 방법으로 putExtra함수를 통해 키와 값을 지정하여 반환할 데이터를 저장합니다.
textView.setOnClickListener{
val intent = Intent()
intent.putExtra("myValue3", "반환값")
setResult(Activity.RESULT_OK, intent)
finish()
}
intent를 통해 전달해야 할 값을 저장했으면 이를 setResult함수로 담아야 Activity를 호출한 쪽으로 데이터를 넘길 수 있습니다. 이때 setResult함수의 첫 번째 매개변수로 RESULT_OK라는 상수값을 지정했습니다. 이는 결과를 받는 Activity 쪽에서 처리결과를 파악하기 위한 용도이며 RESULT_OK값은 곧 정상 처리되었음을 알리기 위한 것입니다.
이제 다른 Activity를 호출한 본래 Activity에서는 onActivityResult 메서드를 생성해 값을 받을 수 있도록 합니다.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
}
위 메서드는 onCreate메서드 외부에 있어야 함에 주의해 주세요. 위와 같은 메서드는 onActivityResult의 자동완성에 의해 만들어진 코드로 resultCode를 통해 이전에 지정했던 RESULT_OK와 같은 상수값을 전달받을 수 있으며
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
}
}
data를 통해서는 setResult를 통해 담긴 Intent를 가져올 수 있습니다. 받은 Intent로는 역시 위에서 값을 가져올 때 사용한 getStringExtra와 같은 함수로 필요한 값을 받게 됩니다.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
Log.d("test", data?.getStringExtra("myValue3"))
}
}
마지막으로 본래 MainActivity에서는 기존에 startActivity를 통해 다른 Acivity를 호출했는데 특정값을 반환받으려면 startActivity대신 startActivityFroResult를 사용해야 합니다. 따라서 기존의 startActivity를 다음과 같이 수정합니다.
startActivityForResult(intent, 1)
intent는 기존의 intent와 같은데 두 번째 매개변수에 1이라는 값을 지정했습니다. 사실 이 매개변수의 값은 임의로 지정이 가능하며 어떤 호출을 통해서 결괏값이 반환되었는지를 확인하기 위한 용도입니다. 예를 들어 하나의 Activity에 다른 Activity를 호출하는 버튼이 2개 이상이 있는 경우 각각 어느 버튼에서 호출한 Activity를 통해 값이 반환되었는지를 구분해야 하는 경우 사용되는 것입니다. 이렇게 입력된 값은 이전에 작성한 onActivityResult 메서드의 requestCode를 통해 확인할 수 있습니다.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
if (requestCode == 1) {
Log.d("test", data?.getStringExtra("myValue3"))
}
}
}
결과를 Log를 통해서 확인하고 있습니다. 만약 Log가 불편하다면 대신 Toast를 사용해도 됩니다.
Toast.makeText(this, data?.getStringExtra("myValue3"), Toast.LENGTH_LONG).show()
Toast는 순간 나타났다가 다시 사라지는 메시지 박스와 같은 것으로 두 번째 매개변수에 표시할 값을 지정하고 세 번째 매개변수를 통해 얼마나 오래 메시지를 표시할지 지정하면 됩니다.
3. 생명 주기 메서드
Activity는 자신의 상황에 따라 생명 주기와 관련된 메서드를 자동으로 호출합니다. 예컨대 Activity가 화면에 나타나면 onStart()를, Activity가 종료되면 onDestroy() 메서드를 호출합니다.
onCreate() | Activity가 생성됨 |
onStart() | Activity가 시작됨, 화면에 표시시작 |
onResume() | Activity가 실행중임 |
onPause() | Activity의 실행이 정지됨, 이런 현상은 Activity화면의 일부가 다른 Activity에 의해 가려지는 상황등에 의해 발생함. |
onStop() | Activity의 실행이 중지됨, 다른 Acitivy로 화면이 완전히 전환됨. |
onDestory() | Activity가 종료됨. |
override fun onStart() {
super.onStart()
Log.d("test", "Activity 시작됨")
}
override fun onStop() {
super.onStop()
Log.d("test", "Activity 중지됨")
}
그런데 위 예제를 보면 Main Activity에서만 로그를 찍고 있습니다. 다른 Activity의 생명주기 메서드를 활용하려면 해당 Activity안에서 생명주기 메서드를 아래와 같이 만들어 두면 됩니다.
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
textView.text = "${intent.getIntExtra("myValue2", 0)}"
textView.setOnClickListener{
val intent = Intent()
intent.putExtra("myValue3", "반환값")
setResult(Activity.RESULT_OK, intent)
finish()
}
}
override fun onStart() {
super.onStart()
Log.d("test", "My Activity 시작됨")
}
override fun onStop() {
super.onStop()
Log.d("test", "My Activity 중지됨")
}
}
'Mobile > Kotlin' 카테고리의 다른 글
[Kotlin] RecyclerView (0) | 2020.12.21 |
---|---|
[Kotlin] Spinner (0) | 2020.12.18 |
[Kotlin] res (0) | 2020.12.17 |
[Kotlin] 위젯 - SeekBar, RatingBar (0) | 2020.12.17 |
[Kotlin] 시작하기 (hello world) (0) | 2020.12.16 |