Skip to content
/ TodoList Public

개인프로젝트 TodoList 애플리케이션. 할 일 목록 애플리케이션

Notifications You must be signed in to change notification settings

deveq/TodoList

Repository files navigation

Todo List

개인프로젝트, Kotlin, Android Studio

개발기간 : 2020.10.18 ~ 2020.10.29

애플리케이션 설명

간단히 할 일을 추가할 수 있는 Todo List 애플리케이션입니다.

참고자료

  1. 오준석의 안드로이드 생존코딩 코틀린편
  2. 깡쌤의 안드로이드 프로그래밍
  3. https://readystory.tistory.com/176 : [준비된 개발자]님의 [Android] AAC ViewModel 을 생성하는 6가지 방법 - ViewModelProvider

TodoList 애플리케이션을 만든 이유

간단한 참고자료1의 책을 이용해 공부하던 중 예제로 있던 TodoList를 조금 더 보완해서 만들 수 있지 않을까 생각하였습니다.
Room을 이용해 로컬 DB를 이용하고, @Query를 이용해 SQL의 Select문을 이용한다면 간단한 검색과 정렬 기능을 추가할 수 있을 것이라 생각였고
상단 Menu 역시 프로젝트를 통해 익힐 수 있을 것이라 생각하여 만들게 되었습니다.

순서

    1. 완성 화면
    1. 사용한 개념 및 기능
    1. 느낀점

완성화면

할 일 추가

add_todo

하단의 EditText에 내용을 입력 후 '추가' Button을 누르면 viewModel객체 내의 MutableLiveData의 value의 값이 변경되도록 설정했습니다.

상세보기 (상세설정)

detail

RecyclerView의 item이 클릭되면 Adapter로 전달된 goToDeatil메서드가 실행되고
bundle에 Serializable을 구현한 Todo객체를 넣어줍니다.
DetailActivity에서 Todo객체를 받아와 처리하는 방식으로 진행했습니다.

완료하기

done

CheckBox 체크 시 isChecked의 값을 todo.isDone 넣어주고, todo.isDone의 값에 따라 취소선(-)이 표시되게 하였습니다.

삭제하기

delete

'X'버튼을 통해 삭제하거나 menu의 완료 삭제를 통해 삭제를 합니다. todoDao의 delete 메서드를 통해 삭제하는 방식으로 진행하였습니다.

검색하기

search


TodoDao.kt
    //Query문을 이용해 키워드로 todoList 얻기.
    @Query("select * from todo where text like '%' ||:text || '%' order by date,time desc")
    fun getTodosByText(text: String) : MutableList
    

Room의 Query어노테이션의 속성에 query문을 넣어주었고, getTodosByText의 매개변수로 들어온 text를 이용하여 검색하고 리스트를 받는 방식으로 진행하였습니다.

MainActivity.kt
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
         ...
         ..
         .
      //검색 기능
        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                //검색어 입력버튼을 누른 후 내용이 있다면
                if (query != "" && query != null) {
                    //검색어를 통해 TodoList를 얻어옴.
                    todoList.value = viewModel.getTodosByText(query)
                } else {
                    setList()
                }
                return true
            }
            override fun onQueryTextChange(newText: String?): Boolean {
                return false
            }
        })

        //검색 닫기를 누른 후 기본 TodoList로 복귀
       searchView.setOnCloseListener {
            setList()
            false
        }
        return super.onCreateOptionsMenu(menu)
    }

정렬하기

sort

메뉴의 등록일 순 얻기는 Todo객체의 PrimaryKey인 registerTime: Long 객체로 Todo객체가 생성될 때
System.currentTimeMills()를 얻습니다.
그것을 기준으로 등록일 순 정렬을 얻었습니다.

날짜순 얻기는 Todo객체의 date와 time을 통해 검색됩니다.

TodoDao.kt
    @Query("select * from Todo order by registerTime desc")
    fun getAll() : MutableList

    //전체 얻기. 날짜순으로 얻기.
    @Query("select * from todo order by date, time desc")
    fun getAllTimeOrder() : MutableList

Room, LiveData, ViewModel

Room, LiveData, ViewModel을 이용한 MVVM패턴을 활용하여
MutableLiveData>타입으로 받고, 
Todo객체를 item_list의 View에 바인딩 해줌으로써
화면에 목록으로써 구현됨.

*Room

  • Entity 생성
@Entity
data class Todo(var text: String?, var isDone: Boolean = false) : Serializable {
    // 등록하는 순간 System의 시간을 받으므로 등록일 순 정렬에 사용할 기준이 됨.
    @PrimaryKey
    var registerTime : Long = System.currentTimeMillis()

    @ColumnInfo
    var hashTag: String? = null

    // 날짜 기준 검색의 기준이 됨.
    @ColumnInfo
    var time: String? = null
    @ColumnInfo
    var date: String? = null
    @ColumnInfo
    var dateLong: Long? = null
    ...
    ..
    .
  • Dao 생성

 @Dao
interface TodoDao {
    //전체 얻기. 기본값. 등록순서로 보이기
    @Query("select * from Todo order by registerTime desc")
    fun getAll() : MutableList

    //전체 얻기. 날짜순으로 얻기.
    @Query("select * from todo order by date, time desc")
    fun getAllTimeOrder() : MutableList

    //할일 키워드로 얻기
    @Query("select * from todo where text like '%' ||:text || '%' order by date,time desc")
    fun getTodosByText(text: String) : MutableList
    ....
    ...
    ..
    .
  • Database 생성

 @Database(entities = [Todo::class], version = 2)
abstract class AppDatabase : RoomDatabase() {
    abstract fun todoDao(): TodoDao
}
  1. ViewModel

 // TodoViewModel 객체를 생성할 때 Application을 생성자에 넣어줘야하기때문에,
// 생성자가 있는 ViewModel을 생성하기 위해서는 내가 만들고자 하는 viewModel을 AndroidViewModel(application)을 상속받아 생성하
// ViewModel을 상속받은 경우는 ViewModelProvider.Factory 인터페이스를 구현한 클래스를 이용해서 생성해야함.


class ViewModelProviderFactory(val context: Context) : ViewModelProvider.Factory{
    override fun  create(modelClass: Class): T {
        return if (modelClass.isAssignableFrom(TodoViewModel::class.java)) {
            TodoViewModel(context) as T
        } else {
            throw IllegalArgumentException()
        }
    }
}
  1. LiveData TodoDao객체에서 todoList 검색 결과를 받은 후 MutableLiveData<List>객체 생성 시 인자로 해당 todoList를 넣어주어 생성
val mutableLiveData = MutableLiveData>(todos)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //뷰모델 받아오기
        viewModel = ViewModelProvider(this, ViewModelProviderFactory(this.application))
            .get(TodoViewModel::class.java)

        //recycler view에 보여질 아이템 Room에서 받아오기
        todoList = viewModel.mutableLiveData
        todoList.observe(this, Observer {
            todayAdapter.itemList = it
            todayAdapter.notifyDataSetChanged()
        })

마치며

이번 프로젝트 덕분에 간단한 기능 뿐만 아니라 다양한 기능들을 활용해 볼 수 있었습니다.
ViewModel이 생성되지 않는 문제점이 발생해 정말 오랫동안 막혀있었습니다....
이것저것 자료도 많이 찾아보았고 덕분에 뷰 모델에 대한 이해도가 한 층 올라간 것 같습니다.
점진적으로 이 프로젝트에 파이어베이스를 활용한 인증 및 파이어스토어를 추가할 예정입니다.

About

개인프로젝트 TodoList 애플리케이션. 할 일 목록 애플리케이션

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages