본문 바로가기
개발노트/Kotlin

10주차 5일 금 뷰모델 개선

by 시계속세상은아직돌아가는중 2023. 9. 15.
package com.example.class5_homework.bookmark

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class BookmarkViewModel : ViewModel() {

    private val _bookmarkList: MutableLiveData<List<BookmarkModel>> = MutableLiveData()
    val bookmarkList: LiveData<List<BookmarkModel>> get() = _bookmarkList
//        .distinctUntilChanged()

//    val bookmarkSwitchEvent:MutableLiveData<Boolean> = MutableLiveData()

    fun addBookmarkItem(item: BookmarkModel?) {
        if (item == null) return

        val currentList = bookmarkList.value.orEmpty().toMutableList()

        val compareItem = currentList.find { it.id == item.id }
        if (compareItem != null) return

        currentList.add(item)
        _bookmarkList.value = currentList
    }

    fun modifyBookmarkItem(position: Int?, item: BookmarkModel?) {

        if (item == null) return

        val findPosition = position ?: findIndex(item)

        val currentList = bookmarkList.value.orEmpty().toMutableList()
        currentList[findPosition] = item
        _bookmarkList.value = currentList

    }

    fun removeBookmarkItem(position: Int?) {
        if (position == null || position < 0) return

        val currentList = bookmarkList.value.orEmpty().toMutableList()
        currentList.removeAt(position)
        _bookmarkList.value = currentList
    }

    fun find(item: BookmarkModel): BookmarkModel? {
        val currentList = bookmarkList.value.orEmpty().toMutableList()
        return currentList.find { it.id == item.id }
    }

    fun findIndex(item: BookmarkModel?): Int {

        val currentList = bookmarkList.value.orEmpty().toMutableList()

        val findItem = item?.let { find(it) }

        return currentList.indexOf(findItem)
    }

    fun compareData(item: BookmarkModel) {

        val compareBookmarkModel = find(item)


        if (compareBookmarkModel != null) {
            if (compareBookmarkModel.isSwitch == item.isSwitch) {
                modifyBookmarkItem(null, item)
            } else {
                removeBookmarkItem(findIndex(item))
            }
        } else {

            addBookmarkItem(item = item)
        }
    }
}

북마크 뷰 모델에서 모든 데이터 처리를 할 수 있도록 개선되었다.

 

또한 수정 로직도 고쳤는데,

 

                putExtra(
                    EXTRA_TODO_MODEL,
                    todoModel?.copy(
                        title = todoTitle.text.toString(),
                        description = todoDescription.text.toString()
                    )
                )
            }

이 부분을 getParcelbleExtra로 받아오는 과정에서 새로운 인스턴스를 생성하였기 때문에 이상한 문제가 발생하는 것을 확인했다. default값으로 id = -1d이고 내가 필요한 불리안식은 false이기 때문에 1차적으로 데이터가 꼬였다.

 

또한

 

    private val editTodoLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                val entryType =
                    result.data?.getStringExtra(TodoContentActivity.EXTRA_TODO_ENTRY_TYPE)
                val position = result.data?.getIntExtra(TodoContentActivity.EXTRA_TODO_POSITION, -1)
                val todoModel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    result.data?.getParcelableExtra(
                        TodoContentActivity.EXTRA_TODO_MODEL,
                        TodoModel::class.java
                    )
                } else {
                    result.data?.getParcelableExtra(
                        TodoContentActivity.EXTRA_TODO_MODEL
                    )
                }

                // entry type 에 따라 기능 분리
                when (TodoContentType.from(entryType)) {
                    TodoContentType.EDIT -> {
                        modifyTodoItem(position, todoModel)
                        Log.d("아이템",todoModel.toString())
                        if(todoModel?.isSwitch == true){
                        setLiveTodo(todoModel)
                        }
                    }

                    TodoContentType.REMOVE -> removeItemTodoItem(position)
                    else -> Unit // nothing
                }
            }
        }

이 부분에서 

   TodoContentType.EDIT -> {
                        modifyTodoItem(position, todoModel)
                        Log.d("아이템",todoModel.toString())
                        if(todoModel?.isSwitch == true){
                        setLiveTodo(todoModel)
                        }
                    }

이 부분의 예외 처리를 해주지 않았기 때문에 오류가 났다.

 

스위치가 체크가 되었을 때만 sharedviewmodel에 데이터를 넣어줘야 했는데, 무차별적으로 데이터를 꽂아줘서 bookmarkviewmodel 리스트 안의 id가 꼬여서 생긴 문제였다.

 

todoSwitch.setOnCheckedChangeListener { view, isSwitch ->

                if (view.isPressed) {
                    onBookmarkChecked(
                        adapterPosition,
                        item,
                        isSwitch
                    )
                }
                Log.d("아이템.북마크 온", item.toString())
            }
        }

이 부분에서 스위치의 동작은 첫 동작 이후 default set인 false가 설정된 다음 이후 내가 준 값이 설정되는 것을 확인했다.

따라서 todoswitch를 의미하는 view부분을 넣어 클릭이 되었을 때만 값이 들어가도록 하였다.

 

참고 사이트

https://stackoverflow.com/questions/38220795/android-setoncheckedchangelistener-runs-twice

 

Android setOnCheckedChangeListener runs twice

This is my code. What can ba a cause? holder.favorite.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton

stackoverflow.com

https://ios-development.tistory.com/175

 

[RxSwift] 4. distinctUntilChanged

개념: 연달아 중복된 값이 올 때 무시 Observable.of(1, 2, 2, 1, 3) .distinctUntilChanged() .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) /* Prints : 1 2 1 3 /*

ios-development.tistory.com

https://www.learnrxjs.io/learn-rxjs/operators/filtering/distinctuntilchanged

 

distinctUntilChanged - Learn RxJS

const source$ = from([1, 1, 2, 2, 3, 3]);

www.learnrxjs.io

 

'개발노트 > Kotlin' 카테고리의 다른 글

11주차 2일 키 리스너  (0) 2023.09.19
11주차 1일 api숨기  (0) 2023.09.18
10주차 4일  (0) 2023.09.14
10주차 3일 이모저  (0) 2023.09.13
10주차 2일 뷰모델  (0) 2023.09.12