github에서 전체 코드 보기
Todolist 앱 만들기 중 firebase cloud firestore 사용하기 부분만 발췌했습니다.
class MyViewModel : ViewModel() {
val liveTodoData = MutableLiveData<List<DocumentSnapshot>>()
//firebase의 firestore 가져오기
val db = Firebase.firestore
// 현재 유저의 아이디 (로 컬렉션을 만들었음)
val userid = FirebaseAuth.getInstance().currentUser?.uid
init {
reload()
}
//firestore에 저장된 데이터 불러오기
fun reload() {
//db.collection(컬렉션이름. 여기서는 userid)
db.collection(userid.toString())
//실시간으로 데이터가져오기
//데이터를 실시간으로 가져오기 때문에
//데이터 삭제, 수정, 추가 한 후 데이터를 다시 받아오지 않아도 됨
.addSnapshotListener { result, e ->
if (e != null) {
return@addSnapshotListener
}
//가져온 결과를 라이브데이터에 넣기
liveTodoData.value = result?.documents
}
}
//일정 추가 - document 추가
fun addTodo(todo: Todo) {
db.collection(userid.toString()).add(todo)
}
//일정 삭제 - 특정 document 삭제
fun deleteTodo(todo: DocumentSnapshot) {
db.collection(userid.toString()).document(todo.id).delete()
}
//할일 완료 - 필드 업데이트
fun doneTodo(todo: DocumentSnapshot) {
val isDone = todo.getBoolean("isDone") ?: false
db.collection(userid.toString()).document(todo.id).update("isDone", !isDone)
}
}
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
//뷰모델 가져오기
val model: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//리사이클러뷰 만들기
binding.recyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter =
TodoAdapter(
layoutInflater,
emptyList(),
onClickDeleteIcon = {
model.deleteTodo(it)
},
onClickDoneIcon = {
model.doneTodo(it)
})
}
//일정 추가 버튼
binding.btnAdd.setOnClickListener {
model.addTodo(Todo(binding.editText.text.toString()))
}
//mutablelivedata 바뀔때마다 adapter에 list 업데이트해주기
model.liveTodoData.observe(this, Observer {
(binding.recyclerView.adapter as TodoAdapter).setData(it)
})
}
}
data class Todo(val text: String, var isDone: Boolean = false)
class TodoAdapter(
val inflater: LayoutInflater,
var list: List<DocumentSnapshot>,
val onClickDeleteIcon: (todo: DocumentSnapshot) -> Unit,
val onClickDoneIcon: (todo: DocumentSnapshot) -> Unit
) :
RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {
inner class TodoViewHolder(val binding: ItemTodoBinding) :
RecyclerView.ViewHolder(binding.root) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
val view = inflater.inflate(R.layout.item_todo, parent, false)
return TodoViewHolder(ItemTodoBinding.bind(view))
}
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
holder.binding.txtTodo.text = list[position].getString("text")
//작업 완료 일때 글자체 처리
if (list[position].getBoolean("isDone") == true) {
holder.binding.txtTodo.apply {
paintFlags = paintFlags or Paint.STRIKE_THRU_TEXT_FLAG //3. 삭선넣기 & 이탤릭체
setTypeface(null, Typeface.ITALIC)
}
} else {
holder.binding.txtTodo.apply {
paintFlags = 0
setTypeface(null, Typeface.NORMAL)
}
}
//할일 완료 처리
holder.binding.txtTodo.setOnClickListener {
onClickDoneIcon.invoke(list[position])
}
//삭제처리
holder.binding.imgDelete.setOnClickListener {
onClickDeleteIcon.invoke(list[position])
}
}
override fun getItemCount(): Int {
return list.size
}
//livedata가 바뀔때마다 adapter의 list를 업데이트해주고
//recyclerview를 다시 그린다.
fun setData(new: List<DocumentSnapshot>) {
list = new
notifyDataSetChanged()
}
}
안녕하세요 혹시
//한번만 가져오기
// .get() //컬렉션 가져오기
// .addOnSuccessListener { result ->
// for (document in result) {
// val todo =
// Todo(document.data["text"] as String, document.data["isDone"] as Boolean)
// datalist.add(todo)
// }
// liveTodoData.value = datalist
// }
// .addOnFailureListener { e ->
// }
이 부분에서 전부 똑같이 했는데 datalist.add(todo)에서 에러가 뜨는데 datalist에 add함수가 없다는 에러가 발생합니다. 혹시 다르게 할 수 있는 방법이 있을까요?