안정성 문제 해결

성능의 원인이 되는 불안정한 클래스에 직면했을 때 안정화해야 합니다. 이 문서에서는 Google Cloud의 사용할 수 있습니다.

강력한 건너뛰기 사용 설정

먼저 강력한 건너뛰기 모드를 사용 설정해야 합니다. 강한 건너뛰기 모드 매개변수가 불안정한 컴포저블을 건너뛸 수 있으며 방법을 사용하여 안정성으로 인한 성능 문제를 해결할 수 있습니다.

자세한 내용은 강력한 건너뛰기를 참고하세요.

클래스를 변경할 수 없게 만들기

불안정한 클래스를 완전히 변경 불가능하게 만들 수도 있습니다.

  • 변경 불가능: 모든 속성의 값이 절대로 변경되지 않는 유형을 나타냅니다. 해당 유형의 인스턴스가 생성된 후 변경되며 모든 메서드는 더 투명합니다
    • 모든 클래스의 속성이 모두 var가 아닌 val인지 확인합니다. 변경할 수 없는 유형이 있습니다
    • String, IntFloat과 같은 기본 유형은 항상 변경할 수 없습니다.
    • 그렇게 할 수 없다면 변경 가능한 속성
  • 안정적: 변경 가능한 유형을 나타냅니다. Compose 런타임은 유형의 공개 속성 또는 메서드가 있는지 여부와 그 시기를 인식 이전 호출과 다른 결과를 생성합니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.

변경할 수 없는 컬렉션

Compose가 클래스를 불안정하다고 간주하는 일반적인 이유는 컬렉션입니다. 앞서 언급했듯이 안정성 문제 진단 페이지의 Compose 컴파일러 List, MapSet와 같은 컬렉션이 변경 불가능하므로 불안정한 것으로 표시합니다.

이 문제를 해결하려면 변경 불가능한 컬렉션을 사용하면 됩니다. Compose 컴파일러 Kotlinx 변경 불가능한 컬렉션 지원이 포함되어 있습니다. 이러한 컬렉션은 불변성을 보장하며 Compose 컴파일러는 알 수 있습니다. 이 라이브러리는 아직 알파 버전이므로 API가 변경될 수 있습니다.

진단 안정성 진단에서 이 불안정한 클래스를 다시 생각해 보세요. 문제 가이드를 참조하세요.

unstable class Snack {
  …
  unstable val tags: Set<String>
  …
}

변경 불가능한 컬렉션을 사용하여 tags를 안정적으로 만들 수 있습니다. 수업에서 tags 유형을 ImmutableSet<String>로 변경합니다.

data class Snack{
    …
    val tags: ImmutableSet<String> = persistentSetOf()
    …
}

이렇게 하면 모든 클래스의 매개변수를 변경할 수 없으며 Compose는 컴파일러가 클래스를 안정적인 것으로 표시합니다.

Stable 또는 Immutable 주석 달기

안정성 문제를 해결할 수 있는 방법은 불안정한 클래스에 주석을 추가하는 것입니다. @Stable 또는 @Immutable를 사용합니다.

클래스에 주석을 달면 컴파일러가 더 이상 실행하지 않는 경우 재정의됩니다. 추론합니다. 이 명령어는 Kotlin의 !! 연산자 여러분은 주의해서 사용하세요. 컴파일러 동작 재정의 예기치 않은 버그가 발생할 수 있습니다. 예를 들어 컴포저블이 재구성되지 않을 때 보게 될 것입니다.

주석 없이 클래스를 안정적으로 만들 수 있는 경우 이러한 방식으로 안정성을 달성하기 위해 노력합니다.

다음 스니펫은 다음과 같이 주석이 달린 데이터 클래스의 간단한 예를 제공합니다. 변경할 수 없습니다.

@Immutable
data class Snack(
…
)

@Immutable 주석을 사용하든 @Stable 주석을 사용하든 Compose 컴파일러는 Snack 클래스를 안정적인 것으로 표시합니다.

컬렉션의 주석 처리된 클래스

List<Snack> 유형의 매개변수가 포함된 컴포저블을 생각해 보세요.

restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  …
  unstable snacks: List<Snack>
  …
)

Snack@Immutable 주석을 추가해도 Compose 컴파일러는 여전히 HighlightedSnackssnacks 매개변수가 불안정하다고 간주됨

매개변수는 컬렉션 유형과 관련하여 클래스와 동일한 문제에 직면합니다. Compose 컴파일러는 항상 List 유형의 매개변수를 불안정하다고 표시합니다. 을 반환합니다.

개별 매개변수를 안정적인 것으로 표시하거나 주석을 달 수 없습니다. 항상 건너뛸 수 있게 만들어야 합니다. 다양한 경로가 있습니다.

불안정한 컬렉션 문제를 해결하는 방법에는 여러 가지가 있습니다. 다음 하위 섹션에서는 이러한 여러 접근 방식을 간략히 설명합니다.

구성 파일

코드베이스의 안정성 계약을 준수한다면 다음을 추가하여 Kotlin 컬렉션을 안정적인 것으로 간주하도록 선택할 수 있습니다. kotlin.collections.*(으)로 안정성 구성 파일을 사용합니다.

변경할 수 없는 컬렉션

불변성의 컴파일 시간 안전성을 위해 다음을 실행할 수 있습니다. List 대신 kotlinx 변경 불가능한 컬렉션을 사용합니다.

@Composable
private fun HighlightedSnacks(
    …
    snacks: ImmutableList<Snack>,
    …
)

래퍼

변경할 수 없는 컬렉션을 사용할 수 없는 경우 직접 컬렉션을 만들 수 있습니다. 이렇게 하려면 주석이 지정된 안정적인 클래스에서 List를 래핑합니다. 일반 래퍼는 가장 적합한 옵션을 선택할 수 있습니다

@Immutable
data class SnackCollection(
   val snacks: List<Snack>
)

그런 다음 이를 컴포저블의 매개변수 유형으로 사용할 수 있습니다.

@Composable
private fun HighlightedSnacks(
    index: Int,
    snacks: SnackCollection,
    onSnackClick: (Long) -> Unit,
    modifier: Modifier = Modifier
)

해결 방법

이러한 접근 방식 중 하나를 취한 후 Compose 컴파일러는 이제 HighlightedSnacks skippablerestartable로 모두 구성 가능

restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
  stable index: Int
  stable snacks: ImmutableList<Snack>
  stable onSnackClick: Function1<Long, Unit>
  stable modifier: Modifier? = @static Companion
)

이제 리컴포지션 중에 Compose는 다음 항목이 없는 경우 HighlightedSnacks를 건너뛸 수 있습니다. 알 수 있습니다.

안정성 구성 파일

Compose 컴파일러 1.5.5부터 안정적인 것으로 간주할 수 있습니다. 이렇게 하면 사용자가 제어하지 않는 클래스(예: 표준 라이브러리 클래스) LocalDateTime과 같은 안정적인 버전을 제공합니다.

구성 파일은 행당 하나의 클래스가 있는 일반 텍스트 파일입니다. 댓글, 단일 및 이중 와일드 카드가 지원됩니다. 구성 예는 다음과 같습니다.

// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>

이 기능을 사용 설정하려면 구성 파일의 경로를 Compose에 전달하세요. 컴파일러 옵션을 제공합니다.

Groovy

kotlinOptions {
    freeCompilerArgs += [
            "-P",
            "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
                    project.absolutePath + "/compose_compiler_config.conf"
    ]
}

Kotlin

kotlinOptions {
  freeCompilerArgs += listOf(
      "-P",
      "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
      "${project.absolutePath}/compose_compiler_config.conf"
  )
}

Compose 컴파일러는 프로젝트의 각 모듈에서 개별적으로 실행되므로 다음과 같은 작업이 가능합니다. 필요한 경우 여러 모듈에 다른 구성을 제공할 수 있습니다. 또는 구성을 만들고 해당 경로를 각 모듈을 마칩니다

여러 모듈

또 다른 일반적인 문제는 다중 모듈 아키텍처와 관련이 있습니다. Compose 컴파일러 모든 비원시 유형이 아닌 경우에만 클래스가 안정적인지 여부를 추론할 수 있습니다. 참조가 명시적으로 안정적인 것으로 표시되었거나 Compose 컴파일러로도 빌드됩니다.

데이터 레이어가 UI 레이어의 별도 모듈에 있는 경우 이런 문제가 발생할 수 있습니다

해결 방법

이 문제를 해결하려면 다음 방법 중 하나를 사용하면 됩니다.

  1. 컴파일러 구성 파일에 클래스를 추가합니다.
  2. 데이터 레이어 모듈에서 Compose 컴파일러를 사용 설정하거나 클래스에 태그를 지정하세요. 필요한 경우 @Stable 또는 @Immutable를 사용합니다.
    • 여기에는 Compose 종속 항목을 데이터 레이어에 추가하는 작업이 포함됩니다. 하지만 Compose 런타임의 종속 항목일 뿐이며 Compose-UI
  3. UI 모듈 내에서 데이터 레이어 클래스를 UI 관련 래퍼에 래핑합니다. 있습니다.

외부 라이브러리를 사용하지 않는 경우에도 동일한 문제가 발생합니다. Compose 컴파일러.

일부 컴포저블은 건너뛸 수 없어야 합니다.

안정성 문제를 해결하기 위해 노력할 때 모든 있습니다. 그렇게 하려고 하면 최적화가 이르게 될 수 있습니다. 그것이 해결되는 것보다 더 많은 문제를 일으키는 것입니다

건너뛸 수 있는 광고인데 별다른 이점이 없는 경우가 많습니다. 코드 유지관리가 어려워질 수 있습니다. 예를 들면 다음과 같습니다.

  • 자주 재구성되거나 전혀 재구성되지 않는 컴포저블
  • 그 자체로는 건너뛸 수 있는 컴포저블을 호출하는 컴포저블입니다.
  • 많은 수의 매개변수가 있고 비용이 많이 드는 등호가 있는 컴포저블 있습니다. 이 경우 매개변수가 있는지 확인하는 데 드는 비용은 비용이 적게 드는 리컴포지션 비용을 상회할 수 있습니다.

컴포저블이 건너뛸 수 있는 경우 약간의 오버헤드가 추가되며 이는 그만한 가치가 없을 수도 있습니다. 있습니다. 다음과 같은 경우 컴포저블에 다시 시작할 수 없도록 주석을 달 수도 있습니다. 여기서 다시 시작할 수 있는 것이 가치보다 많은 오버헤드라고 판단합니다.