[코드 리팩토링] '미주정복' 9일차 - Dialog와 View끼리 data 전달

이윤진·2024년 1월 26일
0

코드 리팩토링

목록 보기
10/12

이전 포스트에서 Dialog의 '네'를 눌렀을 때 View의 리스트 요소가 제대로 삭제되지 않는 에러를 겪었었다.
이번 글에는 그것을 해결한 방법에 대해 쓰려고 한다.

왜 안 되었나?

이전엔 ViewModel의 LiveData를 이용하여 StockNameList를 업데이트 하는 방식을 사용했었다.

그러나 ViewModel에서 데이터가 바뀌는 시기가 init 한 번 뿐이었다.
심지어 데이터를 다시 데이터베이스에서 가져온다고 해도, StockData 테이블에서 데이터가 바뀌는 것이 아니기 때문에 원하는 결과를 가져올 수 없었다.

해결 방법

이러한 문제를 해결하기 위해서 LiveData를 통해 데이터를 변경하기 보단, MutableStateListOf를 compose 함수의 인자로 전달하는 방식을 선택하였다.

@Composable
fun CompanyList(
    companyList: SnapshotStateList<String>
) {
    LazyColumn() {
        items(companyList) {
            CompanyListCard(it, companyList)
        }
    }
}

@Composable
fun CompanyListCard(
    company: String,
    companyList: SnapshotStateList<String>
) {
    // show dialog
    var isClicked by remember {
        mutableStateOf(false)
    }
    if (isClicked) {
        DividendDialog(
            true,
            company,
            onNegativeClick = {
                isClicked = !isClicked
            },
            onPositiveClick = {
                companyList.remove(company)
                isClicked = !isClicked
            }
        )
    }

    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier.clickable {
            isClicked = true
        }
    ) {
        Text(text = stringResource(id = R.string.dot))
        Spacer(modifier = Modifier.padding(2.dp))
        Text(
            text = company,
            style = TextStyle(
                fontSize = 12.sp,
                fontWeight = FontWeight.Normal
            )
        )
    }
}

이렇게 하니 잘 삭제가 되었지만, 다른 화면을 들렸다가 다시 오면 다시 복구가 되었다.
이는 역시 처음 StockNameList를 데이터베이스에서 받아오기 때문이었다. 결국 이를 완벽하게 해결하려면 StockData 테이블과 독립된 다른 데이터베이스 테이블이 필요했다.

데이터베이스 테이블 생성

@Entity
data class CompanyData(
    @ColumnInfo("company") val company : String
){
    @PrimaryKey(autoGenerate = true)
    var idx = 0
}
package com.example.usdividend.data.local.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.example.usdividend.data.type.CompanyData

@Dao
interface CompanyDao {
    @Insert
    fun insertAll(companyData: CompanyData)

    @Query("SELECT company FROM CompanyData")
    fun getCompany() : List<String>

    // 전체 삭제
    @Query("DELETE FROM CompanyData")
    fun deleteAll()

    @Query("DELETE FROM CompanyData WHERE company = :company")
    fun deleteCompany(company : String)
}

이렇게 해서 1일일 때마다 새로 주식 이름 리스트를 갱신하도록 설정했다.

    private fun getStockNameList() = CoroutineScope(Dispatchers.IO).launch {
        val calendar = Calendar.getInstance()
        val day = calendar.get(Calendar.DATE)
        Log.d("day", day.toString())
        if (day == 1){
            companyDao.deleteAll()
            val newList = stockDao.getAllStockName()
            for(new in newList){
                companyDao.insertAll(
                    CompanyData(
                        new
                    )
                )
            }
        }else{
            _stockNameList.postValue(companyDao.getCompany())
        }
    }

그런데...문제가 생겼다.
데이터베이스에서 잘 지워지고 다 잘 작동 되는데..
이상하게 다른 화면을 들렸다 다시 오면 이전 데이터가 또 있다?!
이전에 넣어둔 데이터가 삭제되지 않아서 그렇다고 생각해서

    /************주식 이름 목록 가져오기************/
    viewModel.stockNameList.observe(LocalLifecycleOwner.current) {
        companyList.clear()
        for (stockName in it) {
            companyList.add(stockName)
        }
        Log.d("company", "$it")

이렇게 주식 목록을 넣어주기 전에 clear해주는 코드를 넣었는데도 나아지지 않았다.
분명 데이터베이스에 값이 없는데 어디서 이걸 가져오는 걸까..?
다른 Activity를 다녀오면 괜찮은데 NavigationBar를 통해 움직일 때는 제대로 삭제되지 않는 것을 볼 수 있었다.
이게 LifecycleOwner때문인 것 같다. 완전히 Destroy된 이후에는 제대로 값을 가져왔기 때문이다.
이걸...어떻게 하면 좋지? 잘 모르겠다...

profile
Android/Flutter 개발

0개의 댓글