화면 전환은 액티비티를 전환하는 것으로 이루어진다.
(물론 요즘은 프래그먼트를 이용해서 많이 전환한다.)
그렇다고 액티비티만 안다고 안드로이드 앱을 잘 구성할 수 있는 것은 아니다.
안드로이드의 앱 구성 요소에는 네 가지가 있는데 액티비티는 그 중 한 개일 뿐이다.
- 안드로이드 앱 구성요소 네 가지 1. 액티비티 2. 서비스 3. 브로드캐스트 수신자 4. 내용 제공자 |
앱을 단말에 설치했을 때, 안드로이드 시스템이 이 구성요소 네 가지에 대한 정보를 앱에 요구한다.
이 구성요소들에 대한 정보는 앱 프로젝트에 있는 AndroidManifest.xml 파일에 존재한다.
액티비티 같은 경우 이 파일에 <activity> ... </activity> 태그로 추가해야 새로 만든 액티비티를 화면에 보여줄 수 있다.
액티비티를 시작하는 방법은 두 가지가 있다.
- startActivity() : 단순히 새로운 액티비티를 시작한다.
startActivityForResult(Intent intent, int requestCode) : 새로운 액티비티를 시작하고 해당 액티비티가 끝나면 데이터를 현재 액티비티에 넘겨주는 역할을 하도록 한다.
그러나 현재 startActivityForResult() 메서드는 Deprecated 되었다.
Deprecated된 자세한 이유는 위에 작성했다.
그래서 위를 참조해서 구현하면 될 것 같다.
책에서는 startActivityResult로 구현했는데, 나는 새로운 방법인 registerForActivityResult() 메서드로 구현해 보겠다.
그리고 각 액티비티끼리는 인텐트를 통해서 서로 데이터를 주고 받는다.
코드로 살펴보기
우선 MainActivity가 있는 프로젝트에서 MenuActivity를 추가한다.
그리고 AndroidManifest.xml에 MenuActivity에 대한 정보를 입력해준다.
그러고 나서 MenuActivity의 속성값에 label과 theme을 추가해준다.
theme 속성은 액티비티의 테마를 나타내는데, Theme.AppCompat.Dialog로 설정하면 대화상자 형태로 액티비티가 나타나게 된다.
MainActivity -> MenuActivity로 진입하고 버튼을 누르면 다시 MainActivity로 돌아가게 만들어 볼 것이다.
텍스트 뷰를 두개 추가해주고, 하나는 메인 액티비티에서 넘어온 값을 입력해 줄 것이다.
버튼을 하나 추가해주고 돌아가기 라는 텍스트를 추가해준다.
버튼을 하나 추가해준다.
버튼을 누르면 메뉴 액티비티가 나오게 할 것이다.
startActivityForResult와 다른 점은 onActivityForResult를 Override할 필요가 없어졌다는 점이다.
우선 ActivityResultLauncher<T> 객체를 생성해주고 초기화 해준다.
T는 내가 호출할 액티비티에서 결과값으로 받아올 자료형을 말한다.
registerForActivityResult(Contract 자료형, 콜백 메서드)를 이용해서 ActivityResultLauncher를 초기화 해준다.
초기화 코드를 보면, resultCode를 받는 곳이 있다. onActivityResult 메서드에서는 매개변수가 3개 있었다.
지금은 result 매개변수 하나만 있다. 그리고 requestCode를 따로 받는 부분이 없다.
우선 나는 MenuActivity에서 받아올 resultCode로 9001을 설정했다.
그리고 ActivityResultLauncher<T>에서 T를 나는 intent로 설정했으므로 intent자료형을 result 매개변수를 통해 받아온다.
getData()는, 현재 A 액티비티이고 호출한 B 액티비티가 있다면 B 액티비티에서 setResult() 매개변수의 두번째 인자로 넣어주는 intent 값을 받아온다.
그리고 intent에서 getExtra를 통해 값을 받아와서 토스트 메시지로 출력한다.
버튼을 누르면 메뉴 액티비티가 실행되게 하였다.
메뉴 액티비티에 값을 전달하기 위해 putExtra로 키와 벨류를 넣어주었다.
그리고 startActivityForResult 메서드가 아니라 ActivityResultLauncher 객체의 launch 메서드를 이용해서 intent를 실행하고 새 액티비티로부터 응답을 받는다. 그리고 requestCode가 사라졌다. 이제는 콜백으로만 처리하므로, 굳이 requestCode가 필요가 없게 됐다.
메뉴 액티비티에서는 원래 startActivityForResult()로 불러왔을 때와 같다.
intent를 getIntent()로 받아와서 메인 액티비티에서 넘어온 intent를 받아온다.
그리고 받아온 intent로 StringExtra를 받아오고 난 후 텍스트뷰를 업데이트 시킨다.
그리고 돌아가기 버튼을 누르면 메인 액티비티에 값을 전달하기 위해 9001번의 ResultCode를 넣어주고,
intent로 데이터도 전달했다.
즉, 요약하자면 원래는(startActivityForResult 사용시)
A->B 로 갈때 B를 띄우면서 요청 코드(requestCode)가 있었지만 지금은 필요 없어졌다.
(어차피 콜백 메서드로 처리하므로)
그리고 B->A로 돌아갈 땐 결과 코드(resultCode)와 데이터만 넘겨주면 된다!
실행화면
돌아가기 버튼을 누르면 호출한 액티비티에 9001번의 resultCode를 넘겨준다. 따라서 intent도 잘 넘어간다.
그렇다면 뒤로가기 버튼을 눌렀을 때, 9002번을 넘겨주게 하면 어떻게 될까?
메뉴 액티비티에서 뒤로가기 버튼을 눌러서 액티비티가 종료될 때, 메인 액티비티에 9002번의 결과코드를 넘겨주도록 해봤다.
9002번이 들어온다면 다른 토스트 메시지가 나오도록 해봤다.
이런 식으로 콜백 메서드로만 처리되므로 훨씬 코드가 간단해진 느낌이다.
액티비티 간 화면 전환의 순서를 정하자면 다음과 같다.
- 새로운 액티비티 생성 : XML 레이아웃 파일과 소스 코드 파일을 생성하고 AndroidManifest.xml 파일에 액티비티 정보를 입력한다.
- 메인 액티비티 혹은 다른 액티비티에서 새로운 액티비티를 띄운다. 이 때 만일 결과값을 받아올 것이라면 startActivityResult() 메서드가 아닌 ActivityResultLauncher 객체를 사용해서 실행해야 함을 주의해야 한다.
- 새로 실행된 액티비티가 종료될 때 setResult(결과코드(resultCode), intent)로 응답을 보낸다.
- ActivityResultLauncher객체의 콜백 부분에서 결과코드(resultCode)에 따른 처리를 하도록 한다.
사실 startActivityForResult() 메서드로 그냥 공부하려다가 그래도 이왕 공부하는거 아는 것 보다는 모르는 것을 공부하는 게 나아서 책에 없는 내용이지만 공부해보았다.
처음에는 복잡해 보였는데 확실히 훨씬더 코드가 간단해졌다.CallBack 메서드를 따로 메서드로 만들어서 매개변수로 넣어서 ActivityResultLauncher 객체를 초기화 한다면유지보수도 쉬워지고 코드의 가독성도 좋아질 것 같다.
예시 프로젝트는 위에서 확인 가능하다.
'안드로이드 > 개념' 카테고리의 다른 글
[Android] 플래그와 부가 데이터 - feat. Parcelable과 양방향 데이터 바인딩 사용 (0) | 2021.07.31 |
---|---|
[Android] 인텐트, Intent (0) | 2021.07.31 |
[Android] 레이아웃 인플레이션 (0) | 2021.07.28 |
[Android] Do It! 안드로이드 도전 04. SMS 입력 화면 만들고 글자의 수 표시하기 + 데이터 바인딩, 뷰 모델, 라이브 데이터로 풀어보기 (0) | 2021.07.27 |
[Android] Do It! 안드로이드 도전 03. 두 개의 이미지뷰에 이미지 번갈아 보여주기 (0) | 2021.07.25 |