Fragment中为需Context的ViewModel绑定DataBinding变量的实现与报错解决
你看到的“Classifier 'SCL90RViewModel' does not have a companion object, and thus must be initialized here”提示,根本不是给ViewModel赋值的逻辑有问题,是两个连锁问题触发的:
- 布局里的DataBinding变量名是大写开头的大驼峰写法,导致Kotlin编译器把赋值语句左边的
SCL90RViewModel识别成你定义的ViewModel类本身,而非binding类的可赋值成员属性,所以才会提示你这个类没法直接当变量赋值 - 就算命名改对,你目前的ViewModel构造需要传Context参数,默认的
by viewModels()委托根本创建不出有效实例,后续运行会直接崩溃
1. 修正布局中的DataBinding变量命名
把XML里<variable>的name从SCL90RViewModel改成Kotlin属性通用的小驼峰写法:
<data> <variable name="scl90RViewModel" type="com.example.poy.ui.questionnaires.tools.SCL90RViewModel"/> </data>
这里的核心逻辑: DataBinding生成的Binding类会根据变量名生成对应的setter方法,而Kotlin的合成属性规则只会识别首字母小写的setter对应的属性;如果变量名首字母大写,编译器不会把它当成binding的成员,反而会把这个标识符解析成你引用的类对象,自然就会抛出找不到伴生对象的报错。
2. 修正ViewModel的Context传入方式
你现在直接在ViewModel构造里传Context的写法既容易造成内存泄漏,也没法被系统默认的ViewModelFactory识别创建。推荐改用系统原生支持的AndroidViewModel实现,它天生持有全局Application Context,不需要手动传参,也没有内存泄漏风险:
// 替换原有的ViewModel代码 class SCL90RViewModel(application: Application) : AndroidViewModel(application) { // 直接从Application上下文读取字符串数组 val item = application.resources.getStringArray(R.array.firstArray) }
改完之后,Fragment里原来写的scl90rViewModel: SCL90RViewModel by viewModels()不需要任何修改,系统会自动调用内置的AndroidViewModelFactory创建对应实例。
3. 重新生成DataBinding代码
完成上面的修改后,一定要点Android Studio顶部菜单的Build -> Make Project,让系统重新生成最新的Binding类,否则旧的缓存代码还在,标红提示不会消失。
如果改完还是有标红,检查两个细节:
- 确认XML里
type属性写的ViewModel全路径和你实际代码的包名、类名完全一致,没有拼写错误 - 确认在binding的apply块里赋值时,左侧写的是小驼峰的属性名
scl90RViewModel,不是原来的大驼峰类名
内容的提问来源于stack exchange,提问作者LAO

