TextField прерывает создание при использовании с навигацией Jetpack?

Я пытался собрать простое приложение, используя Compose 1.0.0-beta09, Kotlin 1.5.10 и Jetpack Navigation 2.3.4. В приложении есть одно действие и два фрагмента.

Первый (основной) фрагмент / экран (при нажатии на кнопку происходит переход ко второму фрагменту / экрану): Screen One screenshot

Второй фрагмент: / screen: Скриншот второго экрана

Проблема: после взаимодействия (установки курсора) с TextField на первом экране и последующего нажатия кнопки второй экран загружается, но остается пустым (вызывается onCreateView для SecondFragment, но setContent не работает / экран не не перекомпонованы?). Если я не взаимодействую с TextField, проблемы не возникает. Я тестировал эмуляторы с уровнями API 28 и 30, compose 1.0.0-beta0709, Kotlin 1.4.32 и 1.5.10 с аналогичными результатами.

Пустой экран два

Основные классы:

      class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            AndroidViewBinding(ContentMainBinding::inflate)
        }
    }
}
      class FirstFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = ComposeView(inflater.context).apply {
        setContent {
            FirstScreen( onButtonClick = {
                findNavController().navigate(R.id.nav_second_fragment)
            })
        }
    }
}
      @Composable
fun FirstScreen(onButtonClick: () -> Unit) {
    Column {
        Text("Screen One", color = Color.Blue, fontSize = 30.sp)
        Button(
            onClick = {
                onButtonClick() },
            content = {
                Text(text = "go to Screen Two", color = Color.White)
            })
        TextField(
            value = "",
            onValueChange = {},
            label = { Text(stringResource(R.string.label_enter_value)) },
        )
    }
}
      class SecondFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = ComposeView(inflater.context).apply {

         setContent {
            Column {
                Text("Screen Two", color = Color.Blue, fontSize = 30.sp)
            }
        }
    }
}
      plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdk 30

    defaultConfig {
        applicationId "com.example.composewithnavigation"
        minSdk 28
        targetSdk 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
        useIR = true
    }
    buildFeatures {
        compose true
        viewBinding true
    }
    composeOptions {
        kotlinCompilerExtensionVersion compose_version
        kotlinCompilerVersion '1.5.10'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.5.0'
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling:$compose_version"
    implementation "androidx.compose.ui:ui-viewbinding:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation 'androidx.activity:activity-compose:1.3.0-beta01'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.4'
    implementation 'androidx.navigation:navigation-ui-ktx:2.3.4'

    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
}

1 ответ

Насколько мне известно, в Compose не рекомендуется использовать фрагменты для навигации. Предполагается, что вы создаете несколько экранов, например, здесь FirstScreen Composable. В любом случае, я думаю, что причина того, что setContent не вызывается, заключается в том, что он вызывается из другого setContent из вашего первого фрагмента. Внутри setContent вы делаете навигационный вызов, который перенаправляет его на второй фрагмент, который снова вызывает setContent. Поскольку второй фрагмент уже будет отображаться внутри setContent Composable FirstScreen, вы фактически вкладываете его, что может не поддерживаться compose (я имею в виду, имеет смысл).

Вот почему мы рекомендуем отказаться от фрагментов и вместо этого использовать Composables, которые не требуют явного вызова setContent.

Другие вопросы по тегам