Java.lang.ClassCastException при инициализации моих моделей представления, которые будут созданы во время выполнения

Я прохожу курс для разработчиков Android по основам Android с помощью Compose. Я нахожусь на модуле 6.2 «Использование комнаты для сохранения данных» (уровень моих текущих знаний в области разработки приложений для Android на данный момент, когда я начинаю).

Я работаю над приложением для заметок под названием Outlook Planner

Простое приложение для заметок + простой прогноз погоды. И я основываю структуру своего приложения на Inventory App, найденном на текущем уровне, на котором я прохожу курс.

Мои модели представления HomeViewModel и MakePlanViewModel извлекаются из AppViewModelProvider для сбора информации из базы данных SQLite + Room для отображения списка заметок и операций вставки/обновления соответственно. И они будут использоваться страницами «Home» и «MakePlan» соответственно.

Однако во время выполнения приложение вылетает, и эта ошибка, которую я не могу устранить, напечатана на этой фотографии

Или

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)

Я ожидал, что приложение будет работать нормально; Я получал доступ к своей базе данных, чтобы отображать заметки на домашней странице и вставлять/редактировать заметки со страницы 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. MakePlanViewModel

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 клонируйте мой проект здесь и откройте в Android Studio.

покажите некоторый код, где находится ваш класс провайдера, в котором отображается ошибка

tyczj 16.04.2024 17:26

Готово, @tyczj! Взгляни.

Ryan Barillos 16.04.2024 17:42
1
2
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вероятно, вы не зарегистрировали свое пользовательское Приложение в манифесте.

Согласно документации (выделено мной):

Вы можете предоставить свою собственную реализацию, создав подкласс и указав полное имя этого подкласса в качестве атрибута «android:name» в теге AndroidManifest.xml.

Так:

В AndroidManifest.xml должно быть что-то вроде:

<application
    android:name = "com.example.outlook.planner.OutlookPlannerApplication"
 ....
</application>

Без этого система не будет знать о вашем пользовательском приложении и инициализирует экземпляр класса по умолчанию Application, что приводит к ошибке при попытке привести его к ожидаемому типу.

Большое спасибо за эту информацию! Очень жаль, что в курсе для начинающих это не было отмечено.

Ryan Barillos 17.04.2024 05:38

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