在运行时初始化要创建的视图模型时出现 java.lang.ClassCastException

问题描述 投票:0回答:1

我正在学习 Android 基础知识与 Compose 中的 Android 开发人员课程。 我正在学习第 6.2 单元使用 Room 进行数据持久化(我目前在 Android 应用程序开发方面的知识水平,正如我刚开始的那样)。

我正在开发一款名为 Outlook Planner

的笔记应用程序

一个简单的笔记应用+简单的天气预报。我的应用程序结构基于我在课程中当前级别中找到的库存应用程序

我的视图模型 HomeViewModelMakePlanViewModel 都从 AppViewModelProvider 中提取,以从 SQLite + Room 数据库收集信息,分别用于显示注释列表和插入/更新操作。它们将分别被“Home”和“MakePlan”页面使用。

但是,在运行时,应用程序崩溃了,这个我无法解决的错误是printed in this photo

或者

java.lang.ClassCastException: android.app.Application cannot be cast to com.example.outlook.planner.OutlookPlannerApplication
at com.example.outlook.planner.ui.AppViewModelProviderKt.outlookPlannerApplication(AppViewModelProvider.kt:42)
at com.example.outlook.planner.ui.AppViewModelProvider$Factory$1$2.invoke(AppViewModelProvider.kt:32)
at com.example.outlook.planner.ui.AppViewModelProvider$Factory$1$2.invoke(AppViewModelProvider.kt:30)

我原本以为应用程序可以正常运行;我将访问我的数据库以在 Home 页面中显示注释,并从 MakePlan 页面插入/编辑注释。

不幸的是,以我目前在 Android 应用程序开发方面的有限知识,我不知道从哪里开始诊断问题并修复它。

我正在为一个学校项目制作这个应用程序,我真的不想从头开始构建,因为我已经在这方面投入了大量的工作(并且对构建笔记的在线教程没有帮助) Kotlin + Jetpack Compose 中的应用程序已有几年历史,没有一个类似于 Google 在其示例中提供的任何单一基本方法可供遵循)。

任何帮助将不胜感激。谢谢。

编辑 这是供您查看的代码:

1。 OutlookPlanner应用程序

class OutlookPlannerApplication : Application() {
    /**
     * AppContainer instance used by the rest of classes to obtain dependencies
     */
    lateinit var container: AppContainer

    override fun onCreate() {
        super.onCreate()
        container = AppDataContainer(this)
    }

2。 AppViewModelProvider

package com.example.outlook.planner.ui

import android.app.Application
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.outlook.planner.OutlookPlannerApplication
import com.example.outlook.planner.ui.pages.home.HomeViewModel
import com.example.outlook.planner.ui.pages.makeplan.MakePlanViewModel

/**
 * Provides Factory to create instance of ViewModel for the entire Outlook Planner app
 */
object AppViewModelProvider {
    val Factory = viewModelFactory {
        /**
         * Initializer for [MakePlanViewModel]
         */
        initializer {
            MakePlanViewModel(
                planRepository = outlookPlannerApplication().container.planRepository
            )
//            MakePlanViewModel()
        }

        /**
         * Initializer for [HomeViewModel]
         */
        initializer {
            HomeViewModel(
                planRepository = outlookPlannerApplication().container.planRepository
            )
        }
    }
}
/**
 * Extension function to queries for [Application] object and returns an instance of
 * [OutlookPlannerApplication].
 */
fun CreationExtras.outlookPlannerApplication(): OutlookPlannerApplication =
    (this[AndroidViewModelFactory.APPLICATION_KEY] as OutlookPlannerApplication)

3. HomeViewModel

/**
 * ViewModel to retrieve all items in the Room database.
 */
class HomeViewModel(planRepository: PlanRepository): ViewModel() {
    val homeUiState: StateFlow<HomeUiState> =
        planRepository.getPlanAll().map { HomeUiState(it) }
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(TIMEOUT_MILLIS),
                initialValue = HomeUiState()
            )

    companion object {
        private const val TIMEOUT_MILLIS = 5_000L
    }
}

4。 制作计划视图模型

class MakePlanViewModel(
    savedStateHandle: SavedStateHandle? = null,
    private val planRepository: PlanRepository
): ViewModel() {
    /**
     * Make Plan UI state
     */
    var makePlanUiState by mutableStateOf(MakePlanUiState())
        private set

    /**
     * Initialize private values in presence of an existing Plan object
     */
    fun initialize(planEntity: PlanEntity) {
        /** DO SOMETHING */
    }
//    init {
//        if (savedStateHandle != null) {
//            viewModelScope.launch {
//                makePlanUiState = planRepository.getPlanOne(planId)
//                    .filterNotNull()
//                    .first()
//                    .toItemUiState(true)
//            }
//        }
//    }


    /**
     * Check that no fields are empty
     */
    private fun validateInput(planCheck: Plan = makePlanUiState.plan): Boolean {
        return with(planCheck) {
            note.isNotBlank()
        }
    }

    /**
     * Updates the [makePlanUiState] with the value provided in the argument. This method also triggers
     * a validation for input values.
     */
    fun updateUiState(planUpdated: Plan) {
        makePlanUiState = MakePlanUiState(
            plan = planUpdated,
            fieldNotEmptyAll = validateInput(planUpdated)
        )
    }

    /**
     * Insert + Update current plan
     */
    suspend fun planUpsert() {
        if (validateInput()) {
            planRepository.planUpsert(makePlanUiState.plan.toEntity())
        }
    }
}

还有更多,请告诉我,或者 git 克隆我的项目here并在 Android Studio 中打开

android kotlin android-jetpack-compose runtime-error android-room
1个回答
0
投票

您可能没有在清单中注册自定义应用程序。

根据文档(强调我的):

您可以通过创建子类并指定该子类的完全限定名称作为 AndroidManifest.xml 标记中的“android:name”属性来提供您自己的实现。

所以:

AndroidManifest.xml

中应该是这样的:

<application android:name="com.example.outlook.planner.OutlookPlannerApplication" .... </application>
如果系统不知道您的自定义应用程序,则会初始化默认的 

Application

 类实例,这会在尝试将其转换为您期望的类型时导致错误。

© www.soinside.com 2019 - 2024. All rights reserved.