我想实现什么目标?
我有一个下载图像的任务,但随着屏幕滚动,它将取消以前的下载并开始下载新的图像。我希望当它取消coroutine
下载上一个图像时,它会立即停止并释放bandwidth
新图像,以便更快地下载。
我已经尝试过什么?
我尝试了多种方法来停止,coroutine
但即使在取消后,它仍然会继续进行,直到完成下载coroutine
。当我取消它时,它会生成coroutine
一个变量并停止调用进一步的挂起函数。但问题是,如果它运行多次或从该任务下载图像,除非完成,否则不会取消。Like 循环将完成其迭代,然后协程将被取消。isActive
false
loop
1000000
network
1000000
我已经尝试过这些但没有成功:
job.cancel()
scope.cancel()
Run Code Online (Sandbox Code Playgroud)
我尝试了很多方法来实现这一目标,但没有找到解决方案。我现在无法在我的项目中使用任何库。
这个用例不是通过线程、执行器服务、协程来实现的。因为所有人的行为都是一样的。
更多类似的问题:
我想使用 DataStore 存储一些首选项。但问题是我的应用程序可以有多个用户,因此需要将这些首选项存储在单独的文件中。我得到了一个仅使用一个用户的工作示例,但我正在努力支持多个用户。
这是我的代码的示例:
class DataStorageRepository(private val context: Context, private val userRepository: UserRepository) {
private object PreferencesKeys {
val SETTING_ONE = intPreferencesKey("setting_one")
}
// retrieve datastore for currently logged in user.
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = userRepository.currentRegistration().name)
val userPreferencesFlow: Flow<UserPreferences> = context.dataStore.data.map { preferences ->
val settingOne = preferences[PreferencesKeys.SETTING_ONE] ?: 0
UserPreferences(settingOne)
}
suspend fun storeSettingOne(settingOne: Int) {
context.dataStore.edit { preferences ->
preferences[PreferencesKeys.SETTING_ONE] = settingOne
}
}
data class UserPreferences(val lastUsedToAccountTab: Int)
}
Run Code Online (Sandbox Code Playgroud)
我正在使用Koin
并尝试卸载DataStorageRepository
注销并在登录时重新创建它,但数据存储似乎一直保持活动状态,直到应用程序被终止并且出现以下崩溃: …
android koin android-jetpack coroutinescope android-jetpack-datastore
任何人都可以明确功能之间的关系 CoroutineScope()
和coroutineScope()
?
当我尝试检查源代码时,我发现它们都是CoroutineScope.kt
. 此外,coroutineScope()
是suspend
函数而另一个是normal
函数
以下是我可以找到的文档:
/**
* Creates a [CoroutineScope] that wraps the given coroutine [context].
*
* If the given [context] does not contain a [Job] element, then a default `Job()` is created.
* This way, cancellation or failure or any child coroutine in this scope cancels all the other children,
* just like inside [coroutineScope] block.
*/
@Suppress("FunctionName")
public fun CoroutineScope(context: CoroutineContext): CoroutineScope =
ContextScope(if (context[Job] != …
Run Code Online (Sandbox Code Playgroud) 我需要处理流收集中的当前值和先前值,因此我需要一些具有如下作用的运算符:
----A----------B-------C-----|--->
---(null+A)---(A+B)---(B+C)--|--->
Run Code Online (Sandbox Code Playgroud)
一个想法是这样的:
fun <T: Any> Flow<T>.withPrevious(): Flow<Pair<T?, T>> = flow {
var prev: T? = null
this@withPrevious.collect {
emit(prev to it)
prev = it
}
}
Run Code Online (Sandbox Code Playgroud)
但这样就无法控制执行第一个流程的上下文。有没有更灵活的解决方案?
coroutine kotlin kotlin-coroutines coroutinescope kotlin-flow
我在协程范围内调用 launch 但它不执行。Snackbar 操作监听器正在执行,但启动块由于某种原因没有执行。
CoroutineScope(Dispatchers.Main).launch {
val scope = this
val mn = snackbarManager(R.id.root)
Snackbar
.make(mn.container, R.string.recpt_deleted, Snackbar.LENGTH_LONG)
.setAction(R.string.undo) {
scope.launch { // not executing
Toast.makeText(requireContext(),"Committing",Toast.LENGTH_LONG).show()
Log.d("COMMIT", "calling commit")
}
}
.show()
}
Run Code Online (Sandbox Code Playgroud) android kotlin android-snackbar kotlin-coroutines coroutinescope
withContext
suspend fun <T> withContext(
context: CoroutineContext,
block: suspend CoroutineScope.() -> T
): T (source)
Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns the result.
Run Code Online (Sandbox Code Playgroud)
suspend fun <R> coroutineScope(
block: suspend CoroutineScope.() -> R
): R (source)
Creates a CoroutineScope and calls the specified suspend block with this scope. The provided scope inherits its coroutineContext from the outer scope, but overrides the context’s Job.
Run Code Online (Sandbox Code Playgroud)
withContext采用CoroutineContext,并且似乎都complete
在其所有子级完成之后。
在什么情况下,withContext
或者coroutineScope
应该比其他的首选? …
GlobalScope
我正在重构一些目前在基于结构化并发的方法上启动协程的 Kotlin 代码。我需要在 JVM 退出之前加入代码中启动的所有作业。我的类可以分解为以下接口:
interface AsyncTasker {
fun spawnJob(arg: Long)
suspend fun joinAll()
}
Run Code Online (Sandbox Code Playgroud)
用法:
fun main(args: Array<String>) {
val asyncTasker = createAsyncTasker()
asyncTasker.spawnJob(100)
asyncTasker.spawnJob(200)
asyncTasker.spawnJob(300)
asyncTasker.spawnJob(500)
// join all jobs as they'd be killed when the JVM exits
runBlocking {
asyncTasker.joinAll()
}
}
Run Code Online (Sandbox Code Playgroud)
基于我的GlobalScope
实现如下所示:
class GlobalScopeAsyncTasker : AsyncTasker {
private val pendingJobs = mutableSetOf<Job>()
override fun spawnJob(arg: Long) {
var job: Job? = null
job = GlobalScope.launch(Dispatchers.IO) {
someSuspendFun(arg)
pendingJobs.remove(job)
}
pendingJobs.add(job)
}
override suspend …
Run Code Online (Sandbox Code Playgroud) 如果内部的操作在CoroutineScope(job+Dispatchers.Main){...}
主线程上运行,那么它为什么不违反 Android 的要求,即不允许在主/UI 线程上运行慢(阻塞)操作(网络等)?我可以在此范围内运行阻塞操作,并且 UI 根本不会冻结。
如果有人能解释幕后发生的事情,我将不胜感激。我的猜测是它类似于 JavaScript 如何使用事件循环管理阻塞操作,但我很难找到任何相关材料。
我对协程-调度程序-生命周期范围-异步等待有足够的了解。很明显,所有scope.launch函数都会返回我们可以管理协程生命周期的作业。我唯一无法理解的是我们使用自定义作业创建的自定义范围。
例如:
val myJob = Job()
val customCoroutineScope= CoroutineScope(Dispatchers.IO+myJob)
我认为在这些代码片段之后我可以启动范围并管理它的生命周期和 myJob 引用的内容,但它不起作用。有人可以向我解释一下这个自定义范围的目的和好处吗?
android asynchronous kotlin kotlin-coroutines coroutinescope
在 Kotlin 中启动协程有多种方法。我发现了几个使用GlobalScope
和的例子CoroutineScope
。但后一个是在启动协程时直接创建的:
使用GlobalScope
:
fun loadConfiguration() {
GlobalScope.launch(Dispatchers.Main) {
val config = fetchConfigFromServer() // network request
updateConfiguration(config)
}
}
Run Code Online (Sandbox Code Playgroud)
使用CoroutineScope
实例,在启动协程时直接创建:
fun loadConfiguration() {
CoroutineScope(Dispatchers.Main).launch {
val config = fetchConfigFromServer() // network request
updateConfiguration(config)
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这两种方法有区别吗?
第二种情况不是违反了结构化并发的原则吗?
android kotlin kotlin-coroutines coroutinescope structured-concurrency
coroutinescope ×10
android ×7
kotlin ×7
coroutine ×2
asynchronous ×1
koin ×1
kotlin-flow ×1
suspend ×1
withcontext ×1