본문 바로가기

안드로이드/JetPack

[안드로이드] 3. LiveData

LiveData

데이터의 변화를 관찰하여 화면을 갱신시키기 위한 라이브러리이다. 이해를 위해 이전 문서의 코드를 보자.

result_textView.text = db.todoDao().getAll().toString()

add_button.setOnClickListener {
       db.todoDao().insert(Todo(todo_edit.text.toString()))
       result_textView.text = db.todoDao().getAll().toString()
}

값을 받아 UI에 업데이트하는 똑같은 구문이 두개나 존재한다. 값이 변경될 때 마다 화면 갱신을 위해 저러한 구문을 반복해서 써줘야 되는 것도 문제지만, 만약 한번이라도 까먹고 빠뜨린다면 잘못된 결과를 유저에게 보이게 된다. 

 

위처럼 LiveData의 이점은

  • 데이터와 UI의 일치
  • 메모리 누수 없음
  • 데이터 공유
  • 수명주기를 수동으로 처리하지 않아도 됨

 

LiveData의 구현

위를 실현시키기 위해 우리는 Todo 테이블을 관찰할 필요가 있다. 이를 위해선 아래와 같이 간단하게 구현하면 된다.

@Dao
interface TodoDao {
    @Query("SELECT * FROM Todo")
    fun getAll(): LiveData<List<Todo>> //List<Todo>를 LiveData로 만든 모습

    @Insert
    fun insert(todo: Todo)

    @Update
    fun update(todo: Todo)

    @Delete
    fun delete(todo: Todo)
}

 

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).allowMainThreadQueries().build()

        db.todoDao().getAll().observe(this, Observer { todos -> 
            result_textView.text = todos.toString()
        }) //테이블 변화를 감지 할 경우 todos로 값이 들어온다.

        add_button.setOnClickListener {
            db.todoDao().insert(Todo(todo_edit.text.toString()))
        }
    }
}

위의 코드를 실행하면 observe를 통한 UI 갱신구문 이외에 다른 특별한 코딩 없이 UI가 갱신된다. 액티비티에서 해당 LiveData를 관찰하다가 데이터의 변화가 감지될 경우 람다식으로 구현된 Observer의 onChanged 구문이 수행된다.

 

그리고 다음과 같이 LiveData를 상속받아 구현하는 것도 가능하다.

 class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
        private val stockManager = StockManager(symbol)

        private val listener = { price: BigDecimal ->
            value = price
        }

        override fun onActive() {
            stockManager.requestPriceUpdates(listener)
        }

        override fun onInactive() {
            stockManager.removeUpdates(listener)
        }
    }