1. 异常
Process: cn.itmob.demo, PID: 26458
java.util.NoSuchElementException: Collection contains no element matching the predicate.
at cn.itmob.demo.GetPostDetails.execute(GetPostDetails.kt:45)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a5402d1, Dispatchers.Default]
或者
FATAL EXCEPTION: main
Process: cn.itmob.demo, PID: 3224
java.util.NoSuchElementException: Expected at least one element
at kotlinx.coroutines.flow.FlowKt__ReduceKt.first(Reduce.kt:96)
at kotlinx.coroutines.flow.FlowKt.first(Unknown Source:1)
at cn.itmob.demo.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:47)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at cn.itmob.demo.MainActivity.onCreate(MainActivity.kt:46)
at android.app.Activity.performCreate(Activity.java:7994)
at android.app.Activity.performCreate(Activity.java:7978)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@2a9a367, Dispatchers.Main.immediate]
解决
NoSuchElementException
在刚刚使用 Kotlin
或不小心时就会遇到,主要集中在使用 集合、String
、 或 Flow
时使用 first
、last
、min
、max
、single
、random
等时。
如下是源码文件 _Collections.kt _Strings.kt Reduce.kt 中关于 NoSuchElementException
异常的部分源码:
// _Collections.kt
/**
* Returns the first element.
*
* @throws NoSuchElementException if the list is empty.
*/
public fun <T> List<T>.first(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[0]
}
public fun <T> List<T>.last(): T {
if (isEmpty())
throw NoSuchElementException("List is empty.")
return this[lastIndex]
}
public fun <T> Collection<T>.random(random: Random): T {
if (isEmpty())
throw NoSuchElementException("Collection is empty.")
return elementAt(random.nextInt(size))
}
// Reduce.kt
/**
* The terminal operator that returns the first element emitted by the flow and then cancels flow's collection.
* Throws [NoSuchElementException] if the flow was empty.
*/
public suspend fun <T> Flow<T>.first(): T {
var result: Any? = NULL
collectWhile {
result = it
false
}
if (result === NULL) throw NoSuchElementException("Expected at least one element")
return result as T
}
// _Strings.kt
public fun CharSequence.first(): Char {
if (isEmpty())
throw NoSuchElementException("Char sequence is empty.")
return this[0]
}
如 NoSuchElementException
的字母意思和源码所示这个异常出现在我们要获根据某些条件取值但是集合或FLow为空(empty)或没有符合条件的值时出现。
解决方法主要是:
- 涉及集合、Flow取值时考虑到没值可取的情况,确保不会出现 NoSuchElement 的情况。
- 使用
firstOrNull
lastOrNull
maxOrNull
等方法,Flow
Collections
String
中都有类似方法。