안드로이드 스터디

메인액티비티 코드 분석

mky 2025. 11. 1. 20:20

스터디 재개 전에 지금까지 UMC미션으로 했던 것들을 돌아보며 복습하려고 한다.

//MainActivity.kt
package com.example.flo.activities

import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import com.example.flo.home.HomeFragment
import com.example.flo.locker.LockerFragment
import com.example.flo.look.LookFragment
import com.example.flo.R
import com.example.flo.search.SearchFragment
import com.example.flo.dataclasses.Song
import com.example.flo.activities.SongActivity
import com.example.flo.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val song = Song(
            binding.mainMiniplayerTitleTv.text.toString(),
            binding.mainMiniplayerSingerTv.text.toString()
        )


        binding.mainPlayerCl.setOnClickListener {
            //finish() //현재 액티비티 종료
            val intent = Intent(this, SongActivity::class.java)
            intent.putExtra("title", song.title)
            intent.putExtra("singer", song.singer)
            startActivity(intent)
            //finish() //현재 액티비티 종료
        }

        if (intent.hasExtra("albumname")) {
            Toast.makeText(this, intent.getStringExtra("albumname"), Toast.LENGTH_SHORT).show()
        }

        supportFragmentManager.beginTransaction()
            .replace(R.id.main_frm, HomeFragment())
            .commit()

        //BottomNavigationView를 눌렀을 때 Fragment 변경하기
        binding.mainBnv.setOnItemSelectedListener { item ->
            when (item.itemId) {
                //매인 화면
                R.id.homeFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, HomeFragment())
                        .commit()
                    true
                }

                //둘러보기 화면
                R.id.lookFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, LookFragment())
                        .commit()
                    true
                }

                //검색 화면
                R.id.searchFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, SearchFragment())
                        .commit()
                    true
                }

                //보관함 화면
                R.id.lockerFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, LockerFragment())
                        .commit()
                    true
                }
                else -> false
            }
        }
    }
}

하나씩 천천히 살펴보자.

class MainActivity : AppCompatActivity()

1. MainActivity : 앱의 메인 화면을 담당하는 액티비티. AppcompatActivity 클래스를 상속받음

2. AppcompatActivity : 액티비티 클래스. 라이프사이클, supportFragmentManager, supportActionBar를 멤버로 가지고 있다.

 

private lateinit var binding: ActivityMainBinding

3. 뷰바인딩 사용을 위해 바인딩 객체를 선언해줌. lateinit은 나중에 초기화한다는 키워드로, 초기화하기 전에 사용하면 앱이 크러시가 난다. 또한 var에만 사용가능하다.

override fun onCreate(savedInstanceState: Bundle?)

4. onCreate : 생명주기 메서드, 매개변수인 savedInstanceState:Bundle? 은 액티비티의 이전 상태를 저장하고 복원하는 데 사용되는 데이터 구조이다.

super.onCreate(savedInstanceState)

5. super.onCreate(savedInstanceState) : 부모인 AppcompatActivity의 onCreate메서드를 호출 -> 부모 클래스의 초기화 작업을 먼저 실행하겠다는 뜻. Android는 액티비티를 만들 때 기본적인 시스템 설정, 생명주기 등록, UI 초기화 등 중요한 작업을 부모 클래스에서 처리한다.

enableEdgeToEdge()

Android에서 앱 콘텐츠를 화면의 가장자리까지 확장해주는 함수이다. 상태바와 내비게이션 바 뒤까지 콘텐츠가 표시되도록 설정해, 더 몰입감 있는 UI를 만들 수 있다. 

binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

activity_main.xml 레이아웃 파일을 코드에서 사용할 수 있는 객체로 변환하여 binding객체를 초기화.

  • ActivityMainBinding : activity_main에 대응하는 자동 생성된 클래스
  • inflate(layoutInflater) :xml을 메모리에 올려서 실제 뷰 객체로 만들어주는 과정. ActivityMainBinding의 멤버 함수
  • LayoutInflater는 안드로이드의 클래스로, XML로 작성된 레이아웃을 코드에서 사용할 수 있는 객체로 바꿔주는 역할을 함.

setContentView() : 액티비티가 어떤 레이아웃을 화면에 표시할지 지정하는 메서드. activity_main.xml의 최상위 뷰로 지정

 

supportFragmentManager.beginTransaction()
            .replace(R.id.main_frm, HomeFragment())
            .commit()
  • beginTransaction() : 프래그먼트 변경 작업을 수행하는 함수.
  • replace함수로 교체
  • commit() : 트랜잭션을 최종적으로 실행하는 메서드
  • "." 을 계속 붙이는 이유 -> 메서드 체이닝. 앞의 객체가 반환한 결과에 대해 다음 작업을 이어서 수행하겠다는 뜻
  • 흐름을 정리하면, supportFragmentManager객체의 beginTransaction()메서드가 FragmentTransaction객체(빈 트랜잭션)를 반환->replace메서드가 다시 FragmentTransaction객체(작업이 추가됨)를 반환 -> commit()이 해당 FragmentTransaction의 고유 ID를 Int로 반환
  • 앱을 실행하면 첫 화면을 홈 프래그먼트로 설정
//BottomNavigationView를 눌렀을 때 Fragment 변경하기
        binding.mainBnv.setOnItemSelectedListener { item ->
            when (item.itemId) {
                //매인 화면
                R.id.homeFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, HomeFragment())
                        .commit()
                    true
                }

                //둘러보기 화면
                R.id.lookFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, LookFragment())
                        .commit()
                    true
                }

                //검색 화면
                R.id.searchFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, SearchFragment())
                        .commit()
                    true
                }

                //보관함 화면
                R.id.lockerFragment -> {
                    supportFragmentManager.beginTransaction()
                        .replace(R.id.main_frm, LockerFragment())
                        .commit()
                    true
                }
                else -> false
            }
        }

바텀 메뉴를 눌렀을 때 클릭 이벤트 부여하는 코드. Kotlin에서는 함수의 마지막 매개변수가 람다식일 경우,
그 람다를 괄호 밖에서 중괄호로 바로 쓸 수 있는 문법을 제공하는데, 이걸 트레일링 람다(trailing lambda) 문법이라고 한다. 그래서 자바처럼 소괄호 안에 람다식을 안 쓰고 바로 중괄호에 람다식을 쓰는 것.

람다식은 item을 매개변수, '->' 이후에는 when문을 사용해 각각의 경우에 알맞는 프래그먼트 교체를 구현. 그 후 bool값을 반환해 이벤트 처리 여부를 반환한다(SetOnItemClickListener는 bool값을 반환해야 함). Kotlin의 람다식은 마지막 줄의 값이 반환값이 된다.(암시적 반환)