Activity와 Fragment는 코틀린으로 개발하려면 필수적으로 알아야하는 기본 개념이다.
예전에 배우기도 했고 그냥 이게 뭐다~ 라고 이해하고만 넘어갔어서 이번 기회에 제대로 개념 정리를 해보려고 한다.
Activity란?
안드로이드 앱이 실행되면 화면이 등장하고 UI가 화면 위에 나타나며, 버튼을 터치하거나 스크롤을 하는 등 앱을 사용하게 될 것. 이와 같이 앱의 전반적인 활동을 담당하는 것이 액티비티이며, 액티비티와 xml을 연결해 UI를 표시하고 사용자가 여러 액션을 취할 수 있게 해준다.
액티비티를 생성하고 ViewBinding을 이용해 Layout파일을 결합해준다.
clas MainActivity: AppCompatActivity() {
private lateinit var viewBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(viewBinding.root)
}
}
Activity와 Layout을 결합하는 방법
1. findViewById
- 레이아웃에 있는 뷰를 리소스 id를 통해 원하는 뷰 객체를 가져올 수 있는 메소드. 그 전에 setContentView와 같은 메소드로 xml에 있는 리소스들을 지정한 속성에 맞게 인스턴스를 생성해 메모리에 로드해야 함
- findViewById를 사용해 뷰 객체를 하나씩 가져오게 되면 보일러 플레이트 코드들을 많이 생성하게 되고 이러면 성능상으로 좋지 않기에 kotlin extension, DataBinding, ViewBinding과 같은 대체방법들이 나타나고 있음
2. viewBinding
- 뷰의 갯수대로 코드를 추가해줘야 할 필요가 없음
- Null safety함(Id를 잘못 입력해서 에러가 나는 경우 x)
- Type safety함
3. dataBinding
- View와 데이터를 다이렉트로 연결할 수 있고 양방향 바인딩을 할 수 있음
- <layout> 태그를 사용해 만든 레이아웃을 처리하고 TAG를 삽입
새로운 Activity를 띄우는 방법
Intent: 안드로이드 4대 컴포넌트가 서로 데이터를 주고받기 위한 메시지 객체
4대 컴포넌트란?
- 액티비티: 화면을 구성하는 가장 기본적인 컴포넌트
- 서비스: 백그라운드에서 동작하는 컴포넌트
- 브로드캐스트 리시버: 문자 메시지, 베터리 등 방송 신호를 받아서 처리하는 것
- 콘텐츠 프로바이더: 응용 프로그램 사이 데이터를 공유하기 위한 컴포넌트
명시적 Intent: 버튼 눌렀을 때 메인엑티비티에서 세컨드엑티비티로 이동하기 위해 intent를 생성하고 새로운 액티비티 화면을 띄우는 startActivity() 메소드를 이용해 엑티비티 이동
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val intent = Intent(this, secondActivity::class.java)
startActivity(intent)
}
}
}
암시적 Intent: 전화 걸기, 웹 브라우저 열기, 구글 맵 열기, 메시지 보내기, 카메라 등이 있음
// 웹 브라우저 열기
var intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"))
startActivity(intent)
// 전화 걸기
var intent = Intent(Intent.ACTION_VIEW, Uri.parse("tel:119"))
startActivity(intent)
//구글 맵 열기
var intent = Intent(Intent.ACTION_VIEW, Uri.parse
("https://maps.google.com/maps?q="+37.554264+","+126.913598))
startActivity(intent)
Fragment란?
액티비티 내에서 Activity UI의 일부를 나타내기 위해 고안된 개념.
즉, 하나의 액티비티가 여러 개의 화면을 가지도록 만들기 위해 고안된 개념 -> Activity와 View의 개념을 합쳐놓은 것
Fragment를 사용하는 이유?
Activity의 한계 때문
// 메인 엑티비티 xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_change"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container_smaple"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_change"/>
</androidx.constraintlayout.widget.ConstraintLayout>
class MainActivity : AppCompatActivity() {
//이벤트 처리를 위한 변수
private var postion = FIRST_POSITION
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initTransactionEvent()
}
fun initTransactionEvent() {
//만들어둔 Fragment 생성
val sampleFragment = SampleFragment()
val sampleFragment2 = SampleFragment2()
//SupportFragmentManager로 FragmentManager를 호출
supportFragmentManager.beginTransaction().add(R.id.container_smaple,
sampleFragment).commit()
//beginTranscation을 통해 트랜잭션 작업 생성
binding.btnChange.setOnClickListener {
val transaction = supportFragmentManager.beginTransaction()
when(postion) {
FIRST_POSITION -> {
transaction.replace(R.id.container_smaple, sampleFragment2)
postion = SECOND_POSITION
}
SECOND_POSITION -> {
transaction.replace(R.id.container_smaple, sampleFragment)
postion = FIRST_POSITION
}
}
//작업 수행
transaction.commit()
}
}
//가독성을 위한 상수값 선언
companion object {
const val FIRST_POSITION = 1
const val SECOND_POSITION = 2
}
}
- 처음 화면에 뜨는 default는 FIRST_POSITION에 해당되는 첫번째 프래그먼트
- 좌측의 화면에서 상단의 버튼을 클릭하면 우측의 SECOND_POSITION인 두번째 프래그먼트로 이동
- 우측의 화면에서 상단의 버튼을 클릭하면 좌측의 FIRST_POSITION인 첫번째 프래그먼트로 이동
FragmentManager란?
액티비티와 프레그먼트의 중간에서 서로를 이어주는 역할을 하는 것
- 프레그먼트 트랜잭션: 프레그먼트를 추가, 삭제, 교체 등의 작업을 수행할 수 있게 해주며 행해진 트랜젝션 상태를 프레그먼트 백스택에 저장할 수 있도록 해줌
- 액티비티와 통신: 액티비티에서 특정 이벤트가 발생했을 때, 적절한 동작을 할 수 있게 함
프레그먼트 트랜젝션 설정
<프래그먼트 트랜잭션 설정>
// 프래그먼트 매니저 선언
FragmentManager fragmentManager = getSupportFragmentManager()
// 프래그먼트 트랙잭션 시작
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
// 프래그먼트 트랜잭션 마무리
fragmentTransaction.commit()
<트랜잭션을 이용한 프레그먼트 삽입, 교체, 제거>
// 프레그먼트 추가
fragmentTransaction.add(R.id.fragment_container, new 프레그먼트 이름)
// 프레그먼트 교체
fragmentTransaction.replace(R.id.fragment_container, new 프레그먼트 이름)
// 프레그먼트 제거
fragmentTransaction.remove(프레그먼트)
<프레그먼트 백스택> - 사용하면 이전 상태로 돌아감
// 백스택에 저장
fragmentTransaction.addToBackStack(null)
// 트랜잭션 마무리
fragmentTransaction.commit()
프로젝트를 할 때에도 프레그먼트로 구성할 수 있는 페이지들이 있었는데 엑티비티로만 만들었던 적이 있다.
시간 날 때 해당 엑티비티들을 하나의 엑티비티 위의 프레그먼트로 바꾸는 작업도 해봐야겠다.
'Kotlin' 카테고리의 다른 글
Kotlin 면접준비(2) (2) | 2023.06.04 |
---|---|
Kotlin 면접준비(1) (0) | 2023.06.04 |
Kotlin- 문법1 (0) | 2023.06.02 |
클린 아키텍처(Clean Architecture) (0) | 2023.06.02 |
코틀린 컨벤션 (0) | 2023.06.01 |