[Android] Jetpack - LiveData 사용하기

Jinny·2021년 4월 4일
0

Android

목록 보기
27/32
post-thumbnail

지난 포스팅에서 만든 Todo App에 Live Data를 사용해보겠다!!

🚩 LiveData란?

LiveData는 관찰가능한 데이터 Holder 클래스로, Android Jetpack의 구성요소이다.
지난 포스팅에 사용한 Viewmodel은 이러한 LiveData를 가지고 있다.


예를 들어 위 그림과 같이 음식점 메뉴를 나타내는 ViewModel 안에 LiveData가 있다고 가정하자!
LiveData의 '가격'이 변경되면 UI에서 알아채고, 변경된 데이터를 처리할 수 있다.
안드로이드 3.1 이상부터 LiveData 및 Viewmodel은 데이터 바인딩과 함께 작동한다.

Activity, Fragment 등의 LifeCycle을 인식하여 LifeCycle 내에서만 동작하는 요소로 LifeCycle이 종료되면(화면 destroy) 같이 삭제된다.
그러므로 메모리 누수가 없고, 수명주기 문제를 해결해주어 데이터 관리를 개발자가 하지 않아도 된다는 점 등 많은 이점을 가지고 있다.

LiveData는 옵저버 패턴 관련 즉, 데이터의 변경 사항을 알 수 있다.

🚩 사용하기

🔸 build.gradle - dependencies 에 추가

def lifecycle_version = "2.2.0
// viewModel
implementation "androidx.lifecycle:lifrcycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

🔸 생성 및 사용하기

// ViewModel 생성
val myViewModel = ViewModelProviders.of(this).get(MyDataViewModel::class.java)
val binding = ActivityMainBindind.inflate(layoutInflater)

// 생성한 ViewModel과 Databinding을 연결한 후
binding.viewmodel = myViewModle

// 다음 코드를 추가해준다.
binding.setLifecycleOwner(this)
setContentView(binding.root)

🚩 전체 코드

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private val viewModel : TodoAdapter.MainViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        binding.rvItem.apply {
            layoutManager = LinearLayoutManager(this@MainActivity)
            adapter = TodoAdapter(emptyList(), onClickDelete = {
                viewModel.deleteTodo(it)
            }, onClickItem = {
                viewModel.toggleTodo(it)
            })
        }

        binding.addBtn.setOnClickListener {
            val todo = Todo(binding.addEt.text.toString())
            viewModel.addTodo(todo)
        }

        //관찰하여 UI를 업데이트 하도록 observe() 구현
        viewModel.todoLiveData.observe(this, Observer {
            (binding.rvItem.adapter as TodoAdapter).setData(it)
        })
    }
}

data class Todo(
    val text: String,
    var isDone: Boolean = false
) 

class TodoAdapter(
    private var MyDataset: List<Todo>,
    val onClickDelete: (todo: Todo) -> Unit,
    val onClickItem: (todo: Todo) -> Unit
) :
    RecyclerView.Adapter<TodoAdapter.TodoListHolder>() {
    class TodoListHolder(val binding: ItemTodoBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoAdapter.TodoListHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_todo, parent, false)
        return TodoListHolder(ItemTodoBinding.bind(view))
    }

    override fun getItemCount(): Int = MyDataset.size
    
    // 이 부분 추가!
    fun setData(newData : List<Todo>){
        MyDataset = newData
        notifyDataSetChanged()
    }
    
    override fun onBindViewHolder(holder: TodoListHolder, position: Int) {
        val todo = MyDataset[position]
        holder.binding.tvList.text = todo.text
        if (todo.isDone) {
            holder.binding.tvList.apply {
                paintFlags = paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
                setTypeface(null, Typeface.ITALIC)
            }
        } else {
            holder.binding.tvList.apply {
                paintFlags = 0
                setTypeface(null, Typeface.NORMAL)
            }
        }
        holder.binding.ivDelete.setOnClickListener { onClickDelete.invoke(todo) }
        holder.binding.root.setOnClickListener { onClickItem.invoke(todo) }
    }

    class MainViewModel : ViewModel() {
	// LivaData로 하면 읽기만 가능하니 수정이 가능한 MutableLiveData를 쓴다.
        val todoLiveData = MutableLiveData<List<Todo>>()

        private val data = arrayListOf<Todo>()

        fun toggleTodo(todo: Todo) {
            todo.isDone = !todo.isDone
            // 추가!
            todoLiveData.value = data
        }

        fun addTodo(todo: Todo) {
            data.add(todo)
            // 추가!
            // todoLivaData의 값을 변경된 data로 갱신해준다.
            todoLiveData.value = data
        }

        fun deleteTodo(todo: Todo) {
            data.remove(todo)
            // 추가!
            todoLiveData.value = data
        }
    }
}

출처 : 안드로이드 공식문서 && 썸네일 출처
profile
신입 개발자👩‍💻

0개의 댓글