我正在学习 Android 基础知识与 Compose 中的 Android 开发人员课程。 我正在学习第 6.2 单元使用 Room 进行数据持久化(我目前在 Android 应用程序开发方面的知识水平,正如我刚开始的那样)。
我正在开发一款名为 Outlook Planner
的笔记应用程序一个简单的笔记应用+简单的天气预报。我的应用程序结构基于我在课程中当前级别中找到的库存应用程序。
我的视图模型 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)
我原本以为应用程序可以正常运行;我将访问我的数据库以在 Home 页面中显示注释,并从 MakePlan 页面插入/编辑注释。
不幸的是,以我目前在 Android 应用程序开发方面的有限知识,我不知道从哪里开始诊断问题并修复它。
我正在为一个学校项目制作这个应用程序,我真的不想从头开始构建,因为我已经在这方面投入了大量的工作(并且对构建笔记的在线教程没有帮助) Kotlin + Jetpack Compose 中的应用程序已有几年历史,没有一个类似于 Google 在其示例中提供的任何单一基本方法可供遵循)。
任何帮助将不胜感激。谢谢。
编辑 这是供您查看的代码:
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)
}
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)
/**
* 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 中打开
您可能没有在清单中注册自定义应用程序。
根据文档(强调我的):
所以:您可以通过创建子类并指定该子类的完全限定名称作为 AndroidManifest.xml 标记中的“android:name”属性来提供您自己的实现。
在
AndroidManifest.xml
中应该是这样的:
<application
android:name="com.example.outlook.planner.OutlookPlannerApplication"
....
</application>
如果系统不知道您的自定义应用程序,则会初始化默认的 Application
类实例,这会在尝试将其转换为您期望的类型时导致错误。