Kotlin

Kotlin- Activity와 Fragment

취업하고싶다! 2023. 6. 7. 15:37

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

데이터 모델(다이렉트로 뷰,데이터 연결)
레이아웃(데이터모델 연결해 이름(st)라 하고 button부분에서 다이렉트로 데이터 보여줌)
엑티비티
결과(데이터 잘 들어감)

  • 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