반응형
지난 포스트
목표
이 포스트는 총 5편으로 이루어져 있습니다. 밑줄 친 항목이 이번 포스트에서 다룰 항목입니다.
RoomDatabase 개념
Roomdatabase의 기본 요소인 Entity, Database, Dao 개념/구현 (1편)LiveData, ViewModel, Repository를 이용하여 MVVM 아키텍처 구성(1편)
Insert 구성
Navigation Graph , NavHostFragment추가(2편)각 list, update, add fragment의 layout 및 프래그먼트 구현(2편)Add Fragment를 여는 플로팅 버튼 추가 (2편)DB browser를 통해 database 확인(2편)RecyclerView에 들어갈 ItemLayout과 ListAdapter 추가(3편)RecyclerView와 LiveData 적용하기(3편)위와 같이 Room database에 저장된 값을 Recyclerview와 연결하기 (3편)
Update 구성
Update layout 생성(4편)Update Layout Navigation Graph에 연결(4편)Navigation Argument 추가하기(4편)데이터베이스에 수정된 값 업데이트(4편)
Delete 구성
- 제거 버튼 Action bar에 추가(5편)
- 선택한 데이터 삭제(5편)
- 모든 데이터 삭제(5편)
제거 버튼 Action bar에 추가
제거 아이콘 생성
제거할때 사용할 버튼 아이콘을 만들어보겠습니다.
아래와 같이 만들어주었습니다.
Action menu 생성
제거 버튼이 Action menu에 넣어줄 것이기 때문에, menu resource파일이 필요합니다. 아래와 같이 res아래에 새로운 menu파일을 만들어줍니다.
- res/menu/delete_menu
위에서 생성한 아이콘을 적용하였습니다.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_delete"
android:title="Delete"
android:icon="@drawable/ic_baseline_delete_24"
app:showAsAction="ifRoom"
android:iconTint="@android:color/white"/> //tint적용은 min api level 26이 필요합니다.
</menu>
선택한 데이터 삭제
이제 만들어준 menu를 프래그먼트에 적용해보겠습니다.
Dialog를 띄워서 정말 데이터를 지울것인지 한 번 더 물어보겠습니다. Yes를 누르면 args.currentuser가 뷰 모델에 deleteUser함수에게 전달되어 args.currentuser을 지우게 하겠습니다.
- fragments/update/UpdateFragments
class UpdateFragment : Fragment() {
private val args by navArgs<UpdateFragmentArgs>()
private lateinit var mUserViewModel:UserViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_update, container, false)
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
view.updateFirstName_et.setText(args.currentUser.firstName)
view.updateLastName_et.setText(args.currentUser.firstName)
view.updateAge_et.setText(args.currentUser.age.toString())
view.update_button.setOnClickListener{
updateItem()
}
setHasOptionsMenu(true)
return view
}
private fun updateItem(){
val firstName = updateFirstName_et.text.toString()
val lastName = updateLastName_et.text.toString()
val age = Integer.parseInt(updateAge_et.text.toString())
if (inputCheck(firstName,lastName,updateAge_et.text)){
val updatedUser = User(args.currentUser.id, firstName, lastName,age)
mUserViewModel.updateUser(updatedUser)
Toast.makeText(requireContext(),"UpdatedSuccessfully",Toast.LENGTH_SHORT).show()
findNavController().navigate(R.id.action_updateFragment_to_listFragment)
} else{
Toast.makeText(requireContext(),"Please fill out all field",Toast.LENGTH_SHORT).show()
}
}
private fun inputCheck(firstName:String, lastName:String, age: Editable):Boolean{
return !(TextUtils.isEmpty(firstName)&& TextUtils.isEmpty(lastName)&& age.isEmpty())
}
//추가 시작
//action menu resource파일을 연결해줍니다.
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.delete_menu, menu)
}
//action menu에 아이템이 클릭되었을때
override fun onOptionsItemSelected(item: MenuItem): Boolean {
//id.menu_delete이 클릭되면 deleteUser함수 실행
if(item.itemId == R.id.menu_delete){
deleteUser()//아래에 이어서 만들어보겠습니다.
}
return super.onOptionsItemSelected(item)
}
private fun deleteUser(){ //delteIcon이 나오면 Dialog를 띄워서 물어보겠습니다.
val builder = AlertDialog.Builder(requireContext())
builder.setPositiveButton("Yes"){ _, _ ->
//yes클릭시 viewMOdel.deleteUser를 실행시킵니다. args.currentUser를 삭제하게됩니다.
mUserViewModel.deleteUser(args.currentUser)
Toast.makeText(requireContext(),"Suscessfully removed: ${args.currentUser.firstName}",Toast.LENGTH_SHORT).show()
}
builder.setNegativeButton("No") { _, _ ->
//아무일도 일어나지않습니다.
}
//dialog의 UI세팅입니다.
builder.setTitle("Delete ${args.currentUser.firstName}?")
builder.setMessage("Are you sure to delete ${args.currentUser.firstName}")
//dialog가 UI에 보여집니다.
builder.create().show()
}
//추가 끝
}
선택할 리스트를 삭제할 @delete 을 Dao에 구현하겠습니다.
- data/UserDao
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun addUser(user: User)
@Update
suspend fun updateUser(user:User)
//추가 시작
//선택한 User를 지웁니다.
@Delete
suspend fun deleteUser(user:User)
//모두지웁니다.
@Query("DELETE FROM user_table")
suspend fun deleteAllUsers()
//추가끝
@Query("SELECT * FROM user_table ORDER BY id ASC")
fun readAllData(): LiveData<List<User>>
}
- repository/UserRepository
class UserRepository(private val userDao: UserDao) {
val readAllData: LiveData<List<User>> = userDao.readAllData()
suspend fun addUser(user: User){
userDao.addUser(user)
}
suspend fun updateUser(user:User){
userDao.updateUser(user)
}
//추가시작
suspend fun deleteUser(user:User) { //
userDao.deleteUser(user)
}
suspend fun deleteAllUsers() { //deleteAllUser을 실행합니다.
userDao.deleteAllUsers()
}
//추가 끝
}
- viewmodel/UserViewModel
class UserViewModel(application: Application): AndroidViewModel(application) {
val readAllData:LiveData<List<User>>
private val repository: UserRepository
init {
val userDao = UserDatabase.getDatabase(application).userDao()
repository = UserRepository(userDao) //initialize repository
readAllData = repository.readAllData
}
fun addUser(user: User){
viewModelScope.launch(Dispatchers.IO) {
repository.addUser(user)
}
}
fun updateUser(user:User){
viewModelScope.launch(Dispatchers.IO) {
repository.updateUser(user)
}
}
//추가 시작
fun deleteUser(user:User){
viewModelScope.launch(Dispatchers.IO) {
repository.deleteUser(user)
}
}
fun deleteAllUsers(){
viewModelScope.launch(Dispatchers.IO) {
repository.deleteAllUsers()
}
}
//추가 끝
}
모든 데이터 삭제
모든데이터를 삭제하는 아이콘은 ListFragment actionmenu에 넣어주도록 하겠습니다.
- fragments/list/listFragment
class ListFragment : Fragment() {
private lateinit var mUserViewModel: UserViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_list, container, false)
val adapter = ListAdapter()
val recyclerView = view.recyclerview
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
mUserViewModel = ViewModelProvider(this).get(UserViewModel::class.java)
mUserViewModel.readAllData.observe(viewLifecycleOwner, Observer { user->
adapter.setData(user)
})
view.floatingActionButton.setOnClickListener{
findNavController().navigate(R.id.action_listFragment_to_addFragment) //플로팅 버튼을 누르면 addFragment로 화면전환합니다.
}
//추가시작
//메뉴 추가
setHasOptionsMenu(true)
return view
}
//delete user때와 같은 menu를 추가해주겠습니다.
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.delete_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(item.itemId ==R.id.menu_delete){
deleteAllUsers() //deleteAlluser 함수를 실행시킵니다.
}
return super.onOptionsItemSelected(item)
}
private fun deleteAllUsers() { //deleteUser를 만들어줬을때와 같이 dialog를 만들겠습니다.
val builder = AlertDialog.Builder(requireContext())
builder.setPositiveButton("Yse"){ _, _ ->
mUserViewModel.deleteAllUsers()
Toast.makeText(requireContext(),"Suscessfully removed everything ",
Toast.LENGTH_SHORT).show()
}
builder.setNegativeButton("No") { _, _ ->
}
builder.setTitle("Delete delete everything?")
builder.setMessage("Are you sure to delete everything?")
builder.create().show()
}
//추가 끝
}
repository와 viewmodel에 deleteAllUser에 해당하는 함수를 미리 작성해주었기 때문에, 완료되었습니다.
이제 실행해봅시다.
아래와같이 정상적으로 작동하는 걸 확인할 수 있습니다.
반응형