我正在尝试对使用的Kotlin协程进行单元测试delay().对于单元测试我不关心delay(),它只是减慢测试速度.我想以某种方式运行测试,这种方式在delay()调用时实际上并没有延迟.
我尝试使用委托给CommonPool的自定义上下文来运行协同程序:
class TestUiContext : CoroutineDispatcher(), Delay {
suspend override fun delay(time: Long, unit: TimeUnit) {
// I'd like it to call this
}
override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
// but instead it calls this
}
override fun dispatch(context: CoroutineContext, block: Runnable) {
CommonPool.dispatch(context, block)
}
}
Run Code Online (Sandbox Code Playgroud)
我希望我可以从我的上下文delay()方法返回,但是它调用我的scheduleResumeAfterDelay()方法,我不知道如何将它委托给默认的调度程序.
我正在尝试对我的本地数据库进行后台调用,并使用协同程序使用结果更新UI.这是我的相关代码:
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.Dispatchers.IO
import kotlinx.coroutines.experimental.Dispatchers.Main
import kotlin.coroutines.experimental.CoroutineContext
import kotlin.coroutines.experimental.suspendCoroutine
class WarehousesViewModel(private val simRepository: SimRepository)
: BaseReactViewModel<WarehousesViewData>(), CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Main
override val initialViewData = WarehousesViewData(emptyList())
override fun onActiveView() {
launch {
val warehouses = async(IO) { loadWarehouses() }.await()
updateViewData(viewData.value.copy(items = warehouses))
}
}
private suspend fun loadWarehouses(): List<Warehouse> =
suspendCoroutine {continuation ->
simRepository.getWarehouses(object : SimDataSource.LoadWarehousesCallback {
override fun onWarehousesLoaded(warehouses: List<Warehouse>) {
Timber.d("Loaded warehouses")
continuation.resume(warehouses)
}
override …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用协程在改造中实现 JWT 令牌身份验证和刷新令牌。令牌存储在 Room 数据库中。我应该如何实现 await 调用?
目前我正在使用 runBlocking {...} 调用来等待异步本地/远程响应
例子:
client.addInterceptor {
val accessToken = runBlocking { tokenRepository.getActiveToken() }?.access_token ?: "-"
val request = it.request()
.newBuilder()
.addHeader("Authorization", "Bearer $accessToken")
.build()
return@addInterceptor it.proceed(request)
}
Run Code Online (Sandbox Code Playgroud)
我想遵循的是传统模式:
launch {
withContext(IO){...}
}
Run Code Online (Sandbox Code Playgroud)
我该怎么办?
总的来说,我对 Kotlin 协程和 Android 开发很陌生。在尝试了解它是如何工作的时,我遇到了一个似乎无法解决的错误。
从基本活动中,我尝试连接到 googleApiClient。权限没问题。我希望使用 kotlin 协程以直接方式从 LocationManager 获取位置更新,以便稍后使用此 Location 对象。我第一次在模拟器中改变我的位置时它工作正常,第二次我改变我的位置时,它崩溃了,异常如下:
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 /* …Run Code Online (Sandbox Code Playgroud) 我正在尝试对我用 Kotlin 协程制作的演示器进行单元测试,这也是我第一次使用 Mockito
每当我尝试运行单元测试时,我第一次尝试在协程中对我的视图执行任何操作时都会收到以下错误
Exception in thread "main @coroutine#1 @coroutine#2" java.lang.NullPointerException
at .signin.SignInPresenter$subscribe$1.doResume(SignInPresenter.kt:45)
at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
at kotlinx.coroutines.experimental.DispatchedKt.resumeCancellable(Dispatched.kt:208)
at kotlinx.coroutines.experimental.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:35)
at kotlinx.coroutines.experimental.CoroutineStart.invoke(CoroutineStart.kt:111)
at kotlinx.coroutines.experimental.AbstractCoroutine.start(AbstractCoroutine.kt:161)
at kotlinx.coroutines.experimental.BuildersKt.launch(Builders.kt:68)
at kotlinx.coroutines.experimental.BuildersKt.launch$default(Builders.kt:61)
at .signin.SignInPresenter.subscribe(SignInPresenter.kt:42)
Run Code Online (Sandbox Code Playgroud)
这是我的演示者的相关部分,错误中引用的行是 view.showSigninPanel
class SignInPresenter(
private val view: SignInContract.View,
private val userRepo: ParseAuthController,
private val contextPool: CoroutineContextProvider
) : SignInContract.Presenter {
private val coroutineJobs: MutableList<Job> = mutableListOf()
override fun subscribe() {
view.loadBackgroundImage()
view.setUpSignInPanel()
view.setUpKeyboardListener()
coroutineJobs.add(launch(contextPool.Main) {
if (!userRepo.isAuthenticated()) {
view.showSignInPanel()
subscribeToLoginValidation()
subscribeToPaswordEmailValidation()
} else {
view.launchMainActivity()
}
})
}
Run Code Online (Sandbox Code Playgroud)
呼叫userRepo.isAuthenticated() …
我正在从onCreate(...)调用暂停的函数
override fun onCreate(savedInstanceState: Bundle?) {
...
...
callGetApi()
}
Run Code Online (Sandbox Code Playgroud)
暂停功能为:
suspend fun callGetApi() {....}
Run Code Online (Sandbox Code Playgroud)
但是错误显示挂起函数“ callGetApi”应仅从协程或另一个挂起函数调用
我正在用 Kotlin for Android 组装一个简单的演示应用程序,它使用 Jsoup 检索网页的标题。我正在使用Dispatchers.Main作为上下文进行网络调用。
我的协同程序的理解是,如果我叫launch上Dispatchers.Main它并在主线程运行,但暂停执行,从而不会阻塞线程。
我的理解android.os.NetworkOnMainThreadException是它存在是因为网络操作很重,在主线程上运行时会阻塞它。
所以我的问题是,鉴于协程不会阻塞它运行的线程,它NetworkOnMainThreadException真的有效吗?下面是一些示例代码,它在 处抛出给定的异常Jsoup.connect(url).get():
class MainActivity : AppCompatActivity() {
val job = Job()
val mainScope = CoroutineScope(Dispatchers.Main + job)
// called from onCreate()
private fun printTitle() {
mainScope.launch {
val url ="https://kotlinlang.org"
val document = Jsoup.connect(url).get()
Log.d("MainActivity", document.title())
// ... update UI with title
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以简单地使用Dispatchers.IO上下文运行它并将这个结果提供给主/UI 线程,但这似乎避开了协程的一些效用。
作为参考,我使用的是 Kotlin 1.3。
我想创建一个具有返回值的协程方法.
例如)
fun funA() = async(CommonPool) {
return 1
}
fun funB() = async(CommonPool) {
return 2
}
fun sum() {
launch {
val total = funA().await() + funB().await()
}
}
Run Code Online (Sandbox Code Playgroud)
如果我想要求总和方法,我该怎么办?
喜欢,
fun sum(): Int {
launch {
val total = funA().await() + funB().await()
}
return total
}
Run Code Online (Sandbox Code Playgroud) 我应该在我的build.gradle文件中更改或导入类以在我的Android项目中使用Kotlin 1.3使用稳定的协程函数?
关于我的协同程序的碎片 build.gradle
implementation "org.jetbrains.kotlin:kotlin-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlin:kotlin-coroutines-android:$coroutines_version"
当然我使用的是Android Studio 3.3 Preview