[Android] BaseActivity를 이용한 Activity구현

SangGun Park·2021년 11월 17일
1
post-thumbnail

액티비티던 뷰모델이던 기본이 중요하지

BaseActivity란 무엇일까?🤔

  • BaseActivity란 여러 Activity를 사용할 때 중복되는 코드를 미리 정의하여
    필요한 코드만 구현하도록 사용하는 기본 액티비티입니다.

말로만 설명하면 이해하기 힘드니까 코드로 살펴보면

abstract class BaseActivity<T: ViewDataBinding, R: BaseViewModel>: AppCompatActivity() {

    lateinit var binding: T // 데이터 바인딩
    abstract val TAG :String // 액티비티 태그
    abstract val layoutRes: Int // 바인딩에 필요한 layout
    abstract val viewModel: R // 뷰모델
    lateinit var timer: TimeCheckService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.i(TAG,"onCreate")
        binding = DataBindingUtil.setContentView(this, layoutRes)
        timer = TimeCheckService(this, viewModel.countTime,1000)
        setMarketInfo()
        setDisplayBind()
        setRv()
    }

    override fun onRestart() {
        super.onRestart()
        Log.i(TAG,"onRestart")
    }


    override fun onStart() {
        super.onStart()
        Log.i(TAG,"onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.i(TAG,"onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.i(TAG,"onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.i(TAG,"onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.i(TAG,"onDestroy")
    }

    open fun setDisplayBind(){
    }

    open fun setMarketInfo(){
    }

    fun startTimer(){
        if (!timer.isRunning){
            timer.isRunning = true
            timer.start()
        }
    }

    fun stopTimer(){
        if (timer.isRunning){
            timer.isRunning = false
            timer.time = 1
            timer.cancel()
        }
    }

    fun resetTimer(){
        stopTimer()
        startTimer()
    }


    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> if (timer.isRunning){
                println("다운")
            }
            MotionEvent.ACTION_UP -> if (timer.isRunning){
                println("업")
            }
            MotionEvent.ACTION_MOVE -> if (timer.isRunning){
                println("무브")
            }
        }

        return super.onTouchEvent(event)
    }

    /**
     * 리사이클러뷰를 셋팅
     */
    @SuppressLint("UseCompatLoadingForDrawables")
    open fun setRv(){

    }

}

위의 코드에서 살펴보면 abstract로 선언하여 추상 클래스로 구현하고 AppCompatActivity()를 상속받으며 T: ViewDataBinding, R: BaseViewModel 을 사용하여 데이터 바인딩과 뷰모델을 편리하게 사용할 수 있습니다.

데이터 바인딩 같은 경우에는 lateinit var binding: T 로 늦은 초기화를 사용하여
onCreate 함수에서 binding = DataBindingUtil.setContentView(this, layoutRes)로 layout을 받아 바인딩 객체를 생성합니다.

또한 액티비티마다 중복되는 함수를 필요한 부분에 선언하여 불필요한 코드를 줄일 수 있습니다. 예를 들면 open클래스나 생명주기 함수들을 선언하여 생명주기 함수가 호출될 때 Log를 찍도록 미리 선언 해줄 수 있습니다.
이때 코틀린에서 함수는 open fun setDisplayBind(){} 이런식으로 앞에 open을 붙여 상속이 가능하도록 만들어야 합니다.

☝ 코틀린에서는 기본적으로 open을 명시하지 않은 함수는 final로 선언됩니다.

이제 MainActivity에서 위의 BaseActivity를 상속받는 코드를 보겠습니다.

class MainActivity : BaseActivity<ActivityMainBinding, MainViewModel>() {
    override val TAG : String = MainActivity::class.java.simpleName
    override val layoutRes: Int = R.layout.activity_main
    override val viewModel: MainViewModel by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.i(TAG,"onCreate")
//        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
//        viewModel = ViewModelProvider(this, MainViewModel.Factory(application)).get(MainViewModel::class.java)

    }
}

위와 같은 식으로 TAG, layoutRes, viewModel등의 추상 변수를 override하여 정의해 줍니다.

보통 데이터 바인딩과 뷰모델을 사용하면 onCreate()에서 초기화해주는데 BaseActivity를 상속받았기 때문에 binding = DataBindingUtil.setContentView(this, R.layout.activity_main) 이 부분은 주석처리 했고 viewModel부분은 di를 사용하여 주석처리를 하였습니다. onCreate를 제외한 다른 생명주기 함수를 선언하지 않아도 BaseActivity에서 Log 코드를 적었기 때문에 MainActivity의 로그를 살펴보면 각 생명주기가 호출될 때 Log가 찍히는 것을 볼 수 있습니다.


이렇게 BaseActivity를 사용하면 생명주기 함수나 액티비티별 중복되는 코드를 줄일 수 있다는 장점이 있습니다.😲

profile
배우고 제때 익히니 즐겁지 아니한가

0개의 댓글