TIL) 230407

Hanseul Lee·2023년 4월 8일
0

TIL

목록 보기
21/23

SafeArgs의 매개변수를 nullable로 사용하기

class ChatFragment : BaseFragment<FragmentChatBinding>(FragmentChatBinding::inflate) {

    private val argsFromList by navArgs<ChatFragmentArgs>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        Toast.makeText(context, "?? ${argsFromList.retrieveChatList}", Toast.LENGTH_SHORT).show()
		}
}

이 코드를 그대로 실행시키면 앱이 시작되자마자 강제 종료가 되고 아래 오류가 뜬다.

💡 Caused by: java.lang.IllegalArgumentException: Required argument "retrieveChatList" is missing and does not have an android:defaultValue

Fragment를 호출했을 때 필요한 매개변수 retrieveChatList가 없다는 이야기다. 바꿔 말해서 매개변수의 기본값을 설정하지 않아 이런 오류가 생긴 거다.

Navigation graph의 디자인 탭에서 확인해보면 ChatFragment에서 처음 화면이 시작된다. 이 Fragment는 retrieveChatList를 매개변수로 받고 있는데 이 변수의 기본값이 정해지지 않았다. 그래서 초기에 Null 값일 때 앱이 제대로 실행되지 못한 거다. 따라서 다음처럼 nullabe로 변경해준다.

cf) Array를 체크하면 ChatList를 Array 자료형으로 받게 된다.

xml은 아래처럼 생성된다.

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/chatFragment">

    <fragment
        android:id="@+id/chatFragment"
        android:name="hs.project.cof.presentation.view.ChatFragment"
        android:label="ChatFragment" >
        <action
            android:id="@+id/action_chatFragment_to_settingFragment"
            app:destination="@id/settingFragment" />
        <action
            android:id="@+id/action_chatFragment_to_chatListFragment"
            app:destination="@id/chatListFragment" />
        <argument
            android:name="retrieveChatList"
            app:argType="hs.project.cof.data.db.ChatList"
            app:nullable="true"
            android:defaultValue="@null" />
    </fragment>
		...
</navigation>

Room migration하기

room entity인 데이터 클래스의 자료형을 null을 허용하지 않도록 바꿨더니 다음 오류가 난다.

💡 java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number. Expected identity hash: dbcee3eeb6afed152cb6b133b7e5931a, found: 9c5acc2b016ddfb3f762b8e8c114bfc3

스키마가 바뀌었으니 그에 맞춰서 room을 마이그레이션 하라는 말이다. 아래 코드를 이용해서 버전업을 하여 room을 자동으로 마이그레이션할 수 있다.

// Database class before the version update.
@Database(
  version = 1,
  entities = [User::class]
)
abstract class AppDatabase : RoomDatabase() {
  ...
}

// Database class after the version update.
@Database(
  version = 2,
  entities = [User::class],
  autoMigrations = [
    AutoMigration (from = 1, to = 2)
  ]
)
abstract class AppDatabase : RoomDatabase() {
  ...
}

하지만 적용 후 실행시키면 이런 오류가 뜬다.

💡 error: Schema export directory is not provided to the annotation processor so we cannot import the schema. To generate auto migrations, you must provide `room.schemaLocation` annotation processor argument AND set exportSchema to true. public abstract class ChatListDataBase extends androidx.room.RoomDatabase {

스키마를 기록해야 한다는 거다. 앱 단의 gradle 파일에서 다음과 같이 변경하면 project에 schemas 디렉토리가 생성된다.

// ...

android {
    
    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)
        
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
   
    // ... (buildTypes, compileOptions, etc)

}

// ...

그 후 프로젝트 단에서 다음과 같이 스키마 확인이 가능하다.

0개의 댓글