본문 바로가기
SW/개발

[Android/Kotlin] Todo List 앱을 만들어보자! - 4 (할 일 추가)

by PEKAH 2021. 11. 17.

본 포스트는 Todo List 앱을 만들어보자! - 3 에 이어지는 글입니다.

 

이번에는 메모의 추가 기능을 개발해보겠습니다!

 

앞선 1편에서 gradle 파일에 viewBinding을 설정해주었을 것입니다.

이를 활용해 viewBinding을 적용하도록 하겠습니다.

 

MainActivity.kt

class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
}

- 이제 findViewById 대신에 binding 변수로 xml의 변수에 접근하여 사용할 수 있게 되었습니다.

 

그럼 추가 기능을 개발해볼게요!

 

플로팅버튼을 클릭해 EditTodoActivity로 이동시키도록 하겠습니다.

 

MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    ...
        
    binding.fabAdd.setOnClickListener {
        val intent = Intent(this, EditTodoActivity::class.java).apply {
            putExtra("type", "ADD")
        }
        requestActivity.launch(intent)
    }
}

private val requestActivity = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
       
}

인텐트를 통해 this로부터 EditTodoActivity로 액티비티를 이동시킬거에요.

apply를 통해 함께 보낼 데이터를 key:value 형태로 담아주겠습니다.

EditTodoActivity는 추가와 수정을 동시에 담당하기 때문에, 추가를 할 것인지, 수정을 할 것인지를 구분해주어야 합니다.

하여 "ADD"라는 문자열을 putExtra를 통해 담도록 하겠습니다.

requestActivity는 다시 넘어올 데이터를 처리하기 위해 작성하였습니다!

 

이제 EditTodoActivity로 넘어가봅시다!

여기도 똑같이 viewBinding 처리를 해주겠습니다.

 

EditTodoActivity.kt

class EditTodoActivity : AppCompatActivity() {
    lateinit var binding: ActivityEditTodoBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityEditTodoBinding.inflate(layoutInflater)
        setContentView(binding.root)
    }
}

 

다음으로 main에서 담아 보낸 데이터를 받아 추가인지 삭제인지 구분하도록 하겠습니다.

 

EditTodoActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    val type = intent.getStringExtra("type")

    if (type.equals("ADD")) {
        binding.btnSave.text = "추가하기"
    } else {
        binding.btnSave.text = "수정하기"
    }
}

추가일 경우 버튼을 "추가하기"로, 수정일 경우 "수정하기"로 변경해줍니다.

 

다음과 같이 작성이 된다면 잘 따라오고 계신 것입니다!

 

제목과 내용을 작성한 후 추가하기 버튼을 클릭했을 때 이벤트를 처리하도록 합시다!

제목과 내용 데이터를 Todo 객체로 담아 다시 MainActivity로 보내도록 하겠습니다.

 

EditTodoActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    binding.btnSave.setOnClickListener {
        val title = binding.etTodoTitle.text.toString()
        val content = binding.etTodoContent.text.toString()
        val currentDate = SimpleDateFormat("yyyy-MM-dd HH:mm").format(System.currentTimeMillis())

        if (type.equals("ADD")) {
            if (title.isNotEmpty() && content.isNotEmpty()) {
                val todo = Todo(0, title, content, currentDate, false)
                val intent = Intent().apply {
                    putExtra("todo", todo)
                    putExtra("flag", 0)
                }
                setResult(RESULT_OK, intent)
                finish()
            }
        } else {
         // 수정
        }
    }
}

제목, 날짜, 현재시각을 변수로 만들어줍니다.

현재시각의 경우 SimpleDateFormat을 통해 원하는 포맷으로 만들어줍니다.

작성하지 않은 항목(빈칸)이 있는지 확인한 후, Todo 객체를 만들어줍니다.

아이디의 경우 Auto increment가 작동하기 때문에 따로 설정할 필요없이 0을 넣어줍니다.

제목과 내용, 현재시각을 넣어주고, isChecked의 경우 false로 넣어줍니다.

 

인텐트를 만들어 todo 객체와 추가인지, 수정인지를 구분할 flag를 담아 MainActivity로 전달합니다.

flag는 단순 구분을 위함으로 0일 경우 "추가"처리를, 1일 경우 "수정"처리를 하도록 분기를 나눌 것입니다.

 

이제 MainActivity로 돌아갑시다!

 

setResult를 통해 넘어온 데이터는 requestActivity로 들어옵니다.

넘어온 데이터의 resultCode를 확인한 후 flag를 통해 메모 추가에 대한 작업을 시행합니다.

 

MainActivity.kt

class MainActivity : AppCompatActivity() {
    ...
    lateinit var todoViewModel: TodoViewModel
    ...
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        todoViewModel = ViewModelProvider(this)[TodoViewModel::class.java]
        ...
    }
    
    private val requestActivity = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode == RESULT_OK) {
            val todo = it.data?.getSerializableExtra("todo") as Todo

            when(it.data?.getIntExtra("flag", -1)) {
                0 -> {
                    CoroutineScope(Dispatchers.IO).launch {
                        todoViewModel.insert(todo)
                    }
                    Toast.makeText(this, "추가되었습니다.", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
}

 

EditTodoActivity에서 담은 데이터들은 it.data에 담겨지기 때문에 이를 통해 다시 값을 받아 저장합니다.

데이터베이스에 저장하는 작업은 시간이 꽤 걸리는 작업이기 때문에 메인스레드에서 동작하지 않도록 되어있습니다.

하여 코루틴을 통해 IO스레드가 이 작업을 수행하도록 합니다.

insert 작업은 이전에 만들어두었던 viewModel에서 담당하게 될 것입니다.

viewModel 변수를 생성하고 초기화해준 후, insert 해주도록 하겠습니다.

 

insert는 이전 포스트에서 모두 작업해두었기 때문에 따로 더 작업할 내용은 없습니다!

todoViewModel.insert(todo)를 통해 viewModel -> todoRepository -> todoDao 순으로 타고 들어가 데이터베이스에 저장하게 됩니다.

 

데이터가 잘 저장되었는지 확인은 안드로이드 스튜디오 하단의 App Inspection을 통해 가능합니다.

저장이 잘 되었군요!

하지만 아직 메인화면에 목록이 나타나지 않습니다. 

 

다음시간에는 목록을 불러와 메인화면에 출력하는 작업을 해보도록 하겠습니다!

 

 

 

댓글