kotlin协程抛出java.lang.IllegalStateException:已经恢复,但是获得了值Location [英] kotlin coroutine throws java.lang.IllegalStateException: Already resumed, but got value Location

查看:381
本文介绍了kotlin协程抛出java.lang.IllegalStateException:已经恢复,但是获得了值Location的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一般对Kotlin协程和Android开发还是陌生的.在游玩以了解其工作原理时,我遇到了一个似乎无法解决的错误.

I'm quite new to Kotlin coroutine and Android development in general. While playing around to understand how it worked, I faced an error I can't seem to solve.

在基本活动中,我尝试连接到googleApiClient.权限还可以.我希望使用kotlin协程以直接的方式从LocationManager获取位置更新,以便以后使用此Location对象.第一次更改模拟器中的位置可以正常工作,第二次更改位置时,它会崩溃除了这样的例外:

From a basic activity i try to connect to the googleApiClient. The permissions are ok. I wish to use kotlin coroutines to get location updates from LocationManager in a direct style to use this Location object later on. The first time I changed my position in the emulator it works fine, the second time I change my position, It crashes with an exception like this:

FATAL EXCEPTION: main
    Process: com.link_value.eventlv, PID: 32404
    java.lang.IllegalStateException: Already resumed, but got value Location[gps 48.783000,2.516180 acc=20 et=+59m16s372ms alt=0.0 {Bundle[mParcelledData.dataSize=40]}]
    at kotlinx.coroutines.experimental.AbstractContinuation.resumeImpl(AbstractContinuation.kt:79)
    at kotlinx.coroutines.experimental.AbstractContinuation.resume(AbstractContinuation.kt:72)
    at com.link_value.eventlv.View.Create.NewEventLvActivity$await$2$1.onLocationChanged(NewEventLvActivity.kt:100)
    at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:297)
    at android.location.LocationManager$ListenerTransport.-wrap0(LocationManager.java)
    at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:242)
     at android.os.Handler.dispatchMessage(Handler.java:102)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:6077)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)



override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_new_event_lv)

    askForUserLocation()
    val locationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    val presenter = CreateEventPresenterImpl(this@NewEventLvActivity)

    googleApiClient = GoogleApiClient.Builder(this@NewEventLvActivity)
            .enableAutoManage(this /* FragmentActivity */,
                    this /* OnConnectionFailedListener */)
            .addApi(Places.GEO_DATA_API)
            .addConnectionCallbacks(this)
            .build()
}
override fun onConnected(p0: Bundle?) {
    val locationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    input_address.addTextChangedListener(object: TextWatcher{
        override fun afterTextChanged(p0: Editable?) {
        }

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
        }

        override fun onTextChanged(query: CharSequence?, p1: Int, p2: Int, p3: Int) {
            if (query.toString().length >= 4) {
                launch(UI) {
                    val locationUpdated = locationManager.await(LocationManager.GPS_PROVIDER)
                    input_name.text = Editable.Factory.getInstance().newEditable(locationUpdated.toString())
                }
            }
        }
    })
}

private suspend fun LocationManager.await(locationProvider: String): Location? = suspendCoroutine { cont ->
    try {
        requestLocationUpdates(locationProvider, 0, 0.toFloat(), object : LocationListener {
            override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) {
            }

            override fun onProviderEnabled(p0: String?) {
            }

            override fun onProviderDisabled(p0: String?) {
                cont.resumeWithException(UnknownLocationException())
            }

            override fun onLocationChanged(location: Location?) {
                cont.resume(location)
            }
        })
    } catch (ex: SecurityException) {
        cont.resumeWithException(ex)
    }
}

就好像Kotlin使用相同的Continuation.我不知道我在做什么错,为什么它第二次崩溃了.有人可以启发我吗?提前谢谢.

It's as if Kotlin use the same Continuation. I don't know what I'm doing wrong and why it crashes the second time. Can someone enlighten me. Thks in advance.

推荐答案

根据文档,有可能只恢复一次Continuation.第二个简历将抛出 IllegalStateException 并显示已经恢复,但收到$ proposedUpdate"消息.您可以添加其他检查 continuation.isActive 来防止此异常.最好将Channels用于多个回调,例如位置更新.

According to documentation, it's possible to resume Continuation only single time. Second resume will throw IllegalStateException with "Already resumed, but got $proposedUpdate" message. You can add additional checking continuation.isActive to prevent this exception. It's better to use Channels for multiple callbacks like location updates.

这篇关于kotlin协程抛出java.lang.IllegalStateException:已经恢复,但是获得了值Location的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆