我正在为我的 UI 元素制作一个简单的动画。
我有一个动画组件,它有 2 个不同的动画 - ZoomIn 和 ZoomOut。
每当需要在屏幕上显示 UI 元素(例如按钮)时,就会显示这些动画。
我通常更喜欢在不显示时停用游戏对象。
我为动画编写了以下方法:
私人 IEnumerator ToggleObjectWithAnimation (GameObject gameObj) {
Animator gameObjectAnimator = gameObj.GetComponent(); // Animator 设置为未缩放时间
如果(gameObj.activeSelf == false){
gameObj.transform.localScale = new Vector3 (0, 0, 1.0f);
gameObj.SetActive (true);
gameObjectAnimator.SetTrigger("ZoomIn");
yield return new WaitForSeconds (0.5f);
} else if(gameObj.activeSelf == true) {
gameObjectAnimator.SetTrigger("ZoomOut");
yield return new WaitForSeconds (0.5f);
gameObj.SetActive (false); // 当时间刻度 = 0 时代码不执行
}
收益率返回空;
}
该代码在大多数屏幕上都可以正常工作,但是当我使用 timescale = 0 暂停游戏时会出现问题。
当 timescale 为 0 时,gameObj.SetActive (false) 行不起作用。
我一直在尝试了解 Kotlin 协程是如何工作的,我遇到了这个delay函数。
我对这部作品的理解是,
delay挂起当前线程,与 不同的是sleep,该线程不消耗 CPU 周期并被释放以执行其他任务。delay函数使延续存储在某种任务队列中并释放当前线程。指定时间过后,此任务将安排在可用线程上。我的理解正确吗?此外,调用delay的线程与执行调用delay.
谢谢!
挂起功能在单独的线程上运行?如果不是,那么性能优势是什么?
suspend fun requestToken():Token {..} // takes 2 sec to complete
suspend fun createPost (token:Token){..} // takes 3 sec to complete
suspend fun postItem() {
val token = requestToken()
val post =createPost(token)
processPost(post)
}
Run Code Online (Sandbox Code Playgroud)
因此,当我们到达processPost(post)并且如果挂起函数没有在单独的线程上运行,那么我们必须等待requestToken()和createPost(token)方法完成(即 2+3=5 秒)。根据作者的说法,暂停是异步的,但是如果我们没有产生任何新线程,那么我们如何实现异步行为?
鉴于我们有job1 : Job并且job2 : Job我们想要创建job2一个子节点job1(它们单独创建没有关系)。
声明这种关系的正确方法是什么?以便job1取消时间job2也取消...
我试过了,job1.attachChild(e1.job2 as ChildJob)但这是内部 api。当我从 job1 协程启动 job2 时,我不想做一些 hack。
我是 Kotlin 和协程的新手,我正在尝试了解协程 API,所以我很可能做错了什么。所以我有某种对象的列表,我试图对这些对象中的每一个应用一些长时间运行的处理。
val listOfFoos = listOf(Foo(1), ..., Foo(n))
listOfFoos.forEach { longRunningJob(it) }
fun longRunningJob(foo: Foo) {
runBlocking{
delay(2000) //hardcoded delay for testing
}
//do something else
}
Run Code Online (Sandbox Code Playgroud)
当然,这是并发运行它的完美候选者,所以这里使用的是好的旧线程:
listOfFoos.map { thread(start = true) { longRunningJob(it) } }.forEach { it.join() }
Run Code Online (Sandbox Code Playgroud)
当我测量它的执行时间时,它measureTimeMillis给了我大约 2 秒的时间,这看起来非常好,因为每个都longRunningJob并行运行。但是协程要好得多,因为它没有用于上下文切换的线程那样的开销。所以这是我使用协程的实现:
val deferredResults =
listOfFoos.map { GlobalScope.async { longRunningJob(it) } }
runBlocking {
deferredResults.awaitAll()
}
Run Code Online (Sandbox Code Playgroud)
但是这个实现在大约 4 秒内完成了执行,这根本不是我所期望的,如果我向列表中添加更多元素,执行时间也会增加。
那么我在这里做错了什么?
目前我有这个代码块。
如果用户停留在同一个 Fragment 上,我会apiGetObject从 API获取并且我想用 来更新它resetTime - current(请注意,该值将始终为 3 分钟)。
此代码将延迟该needReload.value = true时间。
GlobalScope.launch(Dispatchers.Main) {
apiGetObject.value?.resetTime?.let {
if (it - System.currentTimeMillis() > 0) {
delay(it - System.currentTimeMillis())
}
}
needReload.value = true
}
Run Code Online (Sandbox Code Playgroud)
现在我检索每个对象onResume以刷新数据(这是必须的)。因此,如果在 3 分钟窗口下恢复 Fragment,则会启动另一个协程。
=> 这使得数据
我想要的是:
我想如果有一个新的协程启动然后前一个被取消/销毁。有没有办法做到这一点(欢迎这个协程的其他解决方案)
注意:我将 MVVM 与 LiveData 一起使用,我得到了apiGetObjectRetrofit 和 RX
我正在尝试在我正在构建的天气应用程序中实现 SwipeToRefreshLayout。当用户滑动刷新时,应该更新ViewModel中的数据,然后相应地更新视图。
这是我的 CurrentWeatherFragment 的片段:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(WeatherResponseViewModel::class.java)
pullToRefresh.setOnRefreshListener(this)
bindUI()
}
override fun onRefresh() {
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(WeatherResponseViewModel::class.java)
bindUI()
pullToRefresh.isRefreshing = false
}
private fun bindUI() = launch {
val currentWeather = viewModel.weather.await()
currentWeather.observe(this@CurrentWeatherFragment, Observer {
if (it == null) return@Observer
loading_icon.visibility = View.GONE
updateLocation("Raleigh")
updateDateToToday()
updateTemperatures(it.currently.temperature.roundToInt(),
it.currently.apparentTemperature.roundToInt(),
it.daily.data[0].temperatureMin.roundToInt(),
it.daily.data[0].temperatureMax.roundToInt())
updateDescription(it.currently.summary)
updateEnvironmentals((it.currently.humidity * 100).roundToInt(), it.currently.windSpeed.roundToInt())
updateWeatherIcon(it.currently.icon)
updateTempChart(it)
updatePrecipChart(it)
})
}
Run Code Online (Sandbox Code Playgroud)
我的视图模型:
class WeatherResponseViewModel (
private val forecastRepository: ForecastRepository,
unitProvider: UnitProvider …Run Code Online (Sandbox Code Playgroud) 如何在kotlin中像多线程一样进行多次启动
我想让它first second永远同时工作!!
像这段代码...
runBlocking {
// first
launch{
first()
}
// second
launch{
second()
}
}
suspend fun first(){
// do something
delay(1000L)
// Recursive call
first()
}
suspend fun second(){
// do something
delay(1000L)
// Recursive call
second()
}
Run Code Online (Sandbox Code Playgroud) 我的应用程序中有一个类似于以下的代码
class MyFragment : Fragment(), CoroutineScope by MainScope() {
override fun onDestroy() {
cancel()
super.onDestroy()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
doSomething()
}
private fun doSomething() = launch {
val data = withContext(Dispathers.IO) {
getData()
}
val pref = context!!.getSharedPreferences("mypref", MODE_PRIVATE)
pref.edit().putBoolean("done", true).apply()
}
}
Run Code Online (Sandbox Code Playgroud)
在生产中,我得到很多NPEs的doSomething(),而访问context。
我的假设是coroutine调用cancel()in后被取消onDestroy(),所以我没有费心检查context空值。但看起来continues即使在cancel()被调用之后也能执行。我认为这会发生,如果cancel()在完成后调用withContext和恢复之前coroutines。
所以我替换doSomething()了以下内容。
private fun doSomething() = launch …Run Code Online (Sandbox Code Playgroud) 我试图在 Android 的后台运行一个任务,我想知道我是否需要指定GlobalScope.launch(Dispatchers.IO) { ... }或者一个简单的GlobalScope.launch { ... }就足够了。我担心的是第二种形式是在主线程还是后台/IO 线程中启动协程?
根据Android 文档,
launch不带Dispatchers.IO参数。当您不传递 aDispatcher来启动时,任何从viewModelScope运行启动的协程都在主线程中运行。
根据Kotlin 文档,
在 GlobalScope 中启动协程时使用的默认调度程序由 Dispatchers.Default 表示并使用共享的线程后台池,因此
launch(Dispatchers.Default) { ... }使用与GlobalScope.launch { ... }.
我知道协程直到最近才处于试验阶段,Android-Kotlin 与纯 Kotlin 开发是不同的,但这些陈述对我来说似乎是矛盾的。