Kotlin协程请求:java.lang.IllegalMonitorStateException: object not locked by thread before notify()

一、前言:

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()方法。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...