代码之家  ›  专栏  ›  技术社区  ›  General Tony

Jetpack Compose中的渲染问题-Android

  •  0
  • General Tony  · 技术社区  · 1 年前

    我目前正在使用Jetpack compose,我的项目中有用于依赖注入的Koin。 将viewModel注入时 @Composable 函数,我从Viewmodel中观察到了一些数据,但这里的问题是我无法预览我的UI,它说渲染问题。

    java.lang.IllegalStateException: KoinApplication has not been started
    at org.koin.core.context.GlobalContext.get(GlobalContext.kt:36)
    at org.koin.compose.KoinApplicationKt.getKoinContext(KoinApplication.kt:52)
    at org.koin.compose.KoinApplicationKt.access$getKoinContext(KoinApplication.kt:1)
    at org.koin.compose.KoinApplicationKt.getKoinScope(KoinApplication.kt:86)
    

    它在预览屏幕的问题面板中抛出上述异常。

    正如上面所说,KoinApplication尚未启动,但我已经在Application类中初始化了我的Koin,并在Manifest中定义了它。

        class MainApplication : Application() {
        override fun onCreate() {
            super.onCreate()
            startKoin {
                androidLogger()
                androidContext(this@MainApplication)
                modules(ApiModule)
                modules(appModule)
            }
        }
    }
    
        <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ComposeRetrofit"
        android:name=".MainApplication"
        tools:targetApi="31">
    

    这是我的合成代码,

    @Preview
    @Composable
    fun ViewForMainScreen(){
        MainScreen()
    }
    
    @Composable
    fun getApplianceViewModel(): ApplianceViewModel {
        return koinViewModel()
    }
    
    @Composable
    fun getAddressViewModel(): AddressViewModel {
        return koinViewModel()
    }
    
    @Composable
    fun MainScreen(){
        val addressViewModel = getAddressViewModel()
        val address by addressViewModel.addressApiResponse.observeAsState(initial = null)
    
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .height(100.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            Button(
                onClick = { addressViewModel.callAddressApi() },
                modifier = Modifier
                    .fillMaxWidth()
                    .height(40.dp)
                    .padding(start = 40.dp, end = 40.dp)
            ) {
                Text(text = address?.mailBox ?: "Country")
            }
            Spacer(modifier = Modifier.height(20.dp))
            Text(
                text = address?.fullAddress ?: "Full Address",
                modifier = Modifier.padding(start = 40.dp, end = 40.dp)
            )
        }
    }
    

    这里有什么问题!有办法解决吗?

    感谢您提前回答!

    1 回复  |  直到 1 年前
        1
  •  1
  •   Alexander Hoffmann    1 年前

    Android Studio不使用应用程序类来渲染预览。因此,依赖项注入不起作用。

    这个 suggested workaround 这是为了创建另一个可组合的,它从视图模型中获取参数。

    例如,如果您有一个名为 ShoppingCartScreen 在其中注入视图模型,创建另一个具有名称的屏幕 ShoppingCartScreenContent . 购物车屏幕 然后从视图模型中提取所有数据,并将其作为参数传递到 购物车屏幕内容 .

    或者,两种可堆肥都可以有相同的名称。它们只是因参数类型而异。

    在您的情况下,您可以这样重构它:

    @Composable
    fun MainScreen(){
        val addressViewModel = getAddressViewModel()
        val address by addressViewModel.addressApiResponse.observeAsState(initial = null)
        val onClick = remember { addressViewModel.callAddressApi() }
        MainScreen(address, onClick)
    }
    
    @Composable
    fun MainScreen(address: Address, onClick: () -> Unit){
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .height(100.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            Button(
                onClick = onClick,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(40.dp)
                    .padding(start = 40.dp, end = 40.dp)
            ) {
                Text(text = address?.mailBox ?: "Country")
            }
            Spacer(modifier = Modifier.height(20.dp))
            Text(
                text = address?.fullAddress ?: "Full Address",
                modifier = Modifier.padding(start = 40.dp, end = 40.dp)
            )
        }
    }
    
    @Preview
    @Composable
    fun MainScreenPreview(){
        MainScreen(
            address = Address(), // Create some dummy data here
            onClick = {}
        )
    }