美文网首页
Kotlin协程请求:java.lang.IllegalMoni

Kotlin协程请求:java.lang.IllegalMoni

作者: 因为我的心 | 来源:发表于2023-04-20 15:10 被阅读0次

    一、前言:

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

    相关文章

      网友评论

          本文标题:Kotlin协程请求:java.lang.IllegalMoni

          本文链接:https://www.haomeiwen.com/subject/ydwrjdtx.html