一、前言:
Kotlin 协程请求报错:java.lang.IllegalMonitorStateException: object not locked by thread before notify()
二、解决:
1、网上解决方案(不能解决问题)
这个错误通常是因为在协程中使用了 Java 的 wait() 和 notify() 方法,但是没有正确地使用 synchronized 关键字来锁定对象。在 Kotlin 协程中,应该使用 suspendCoroutine() 函数来挂起协程,而不是使用 wait() 和 notify() 方法。如果需要等待某个条件满足,可以使用 withContext() 函数来切换到另一个协程上下文,等待条件满足后再切换回来。如果必须使用 wait() 和 notify() 方法,那么需要确保在调用这些方法之前,已经使用 synchronized 关键字锁定了对象。
例如:
synchronized(obj) {
obj.wait()
}
这样就可以避免 "object not locked by thread before notify()" 错误。
2、自己的解决方案
1、先说一下事件发生的前提条件
- 我使用的框架是
hegaojian_JetpackMvvm
- 在第一次请求时没有问题,再次刷新就会报错;
- 网络请求到数据,可以正常打印;
- 刷新页面的时候就会报错;
- 根据上面几条,基本可以推断出是自己业务逻辑的报错,跟网络请求和框架无关;
2、解决方法
1、开始请求
fun requestNet() {
//请求数据
mainViewModel.getDiscoverData(productType)
}
2、真正的请求,调用MVVM的协程
fun getDiscoverData(productType: Int?) {
//设置上传参数
RequestParameterUtils.clearParams()
val map = RequestParameterUtils.getMapData()
request({ apiService.getDiscoverData(map) }, {
mainDiscoverData.value = it
}, {
Log.d("home", "---error1:${it.errorLog}")
}, false)
}
3、返回数据监听
注意:数据监听可以放到任何一个方法中,不一定非要在createObserver()方法。
//精选数据
var mainDiscoverData: MutableLiveData<NewBookComicStoare> = MutableLiveData()
//监听数据
mViewModel.mainDiscoverData.observe(this) {
try {
it?.let {
//banner数据
bannerList = it?.banner
list = it?.label
hotList = it.hot_word
//出现问题的就是这个方法
initDataTop()
initRefresh()
mainAdapter.setList(list)
}
} catch (e: Exception) {
//java.lang.IllegalMonitorStateException: object not locked by thread before notify()
MyToash.Log("home", "----e1:${e.toString()}")
}
}
4、报错的类
var firstBanner = true
var xBanner: XBanner? = null
val data by lazy { ArrayList<CustomViewsInfo>() }
private fun initDataTop() {
if (firstBanner || xBanner == null) {
firstBanner = false
//正常逻辑处理.........
} else {
firstBanner.notify()
}
}
注意:第2次请求时xBanner!=null,走下面的else 发现是 firstBanner.notify()去刷新,报错的是这个(直接删除就不会报错了)。
得出结论:MVVM框架和Kotlin协程请求没有任何问题,是我们自己的业务逻辑导致的报错。
5、true.notify()为什么报错?
notify()方法
必须在synchronized块中调用
,否则会抛出IllegalMonitorStateException异常
。这是因为notify()
方法需要获取对象的监视器锁,而如果没有在synchronized块中获取锁
,就无法调用notify()
方法。因此,正确的使用方式是在synchronized
块中调用notify()
方法。
网友评论