Skip to content

Commit 7d29fe0

Browse files
authored
Merge pull request #15 from algolia/feature/remove-coroutines
Feature/remove coroutines
2 parents 8619995 + ba136b8 commit 7d29fe0

File tree

3 files changed

+48
-50
lines changed

3 files changed

+48
-50
lines changed

dependency.gradle

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,20 @@ ext.with {
1414
constraintLayout = '1.1.2'
1515
espresso = '3.0.2'
1616

17-
archRuntime = '1.1.1'
18-
archCompiler = '1.1.1'
19-
2017
kotlins = '1.2.70'
21-
coroutines = '0.26.1'
2218

2319
bintray = '1.8.4'
2420
maven = '2.1'
2521

2622
dependency_jvm = [
2723
kotlin_stdlib : "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlins",
28-
kotlin_reflection: "org.jetbrains.kotlin:kotlin-reflect:$kotlins",
2924
kotlin_test : "org.jetbrains.kotlin:kotlin-test:$kotlins",
3025
kotlin_test_junit: "org.jetbrains.kotlin:kotlin-test-junit:$kotlins"
3126
]
3227
dependency_android = [
3328
appcompat : "com.android.support:appcompat-v7:$appcompat",
3429
constraint_layout : "com.android.support.constraint:constraint-layout:$constraintLayout",
35-
arch_extensions : "android.arch.lifecycle:extensions:$archRuntime",
36-
arch_compiler : "android.arch.lifecycle:common-java8:$archCompiler",
3730
espresso : "com.android.support.test.espresso:espresso-core:$espresso",
38-
design : "com.android.support:design:$design",
39-
coroutines : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
31+
design : "com.android.support:design:$design"
4032
]
4133
}

ui/build.gradle

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ dependencies {
3333

3434
implementation dependency_jvm.kotlin_stdlib
3535

36-
implementation dependency_android.coroutines
3736
implementation dependency_android.appcompat
3837
implementation dependency_android.constraint_layout
3938
implementation dependency_android.design
@@ -44,10 +43,4 @@ dependencies {
4443

4544
testImplementation dependency_jvm.kotlin_test
4645
testImplementation dependency_jvm.kotlin_test_junit
47-
}
48-
49-
kotlin {
50-
experimental {
51-
coroutines "enable"
52-
}
53-
}
46+
}

ui/src/main/kotlin/com/algolia/instantsearch/voice/ui/RippleView.kt

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package com.algolia.instantsearch.voice.ui
22

33
import android.animation.AnimatorSet
4+
import android.annotation.SuppressLint
45
import android.content.Context
56
import android.graphics.Canvas
6-
import android.os.Looper
7+
import android.os.Build
78
import android.util.AttributeSet
89
import android.view.View
9-
import kotlinx.coroutines.experimental.*
10-
import kotlinx.coroutines.experimental.android.Main
11-
import kotlinx.coroutines.experimental.android.UI
12-
import kotlinx.coroutines.experimental.android.awaitFrame
1310

1411
/** A View displaying a ripple effect. */
1512
class RippleView : View {
13+
1614
enum class State {
1715
None,
1816
Playing,
@@ -29,60 +27,69 @@ class RippleView : View {
2927
init(attrs)
3028
}
3129

30+
private val fps = 1000L / 60L
31+
3232
/** All circles used in this RippleView, generated during [init]. */
3333
private var circles = listOf<DrawableSprite>()
3434
/** Current animations, filled when [State.Playing] triggers [animation] and emptied when [State.Stopped]. */
3535
private val animations = mutableMapOf<Int, AnimatorSet>()
3636

37+
/** This runnable invalidate the view at 60 fps. */
38+
private val runnableFps = object : java.lang.Runnable {
39+
40+
override fun run() {
41+
invalidate()
42+
postRunnableFps(this, fps)
43+
}
44+
}
45+
46+
/** This runnable generates an animation at each [interval][circleCount]. */
47+
private val runnableAnimation = object : Runnable {
48+
49+
private var index = 0
50+
51+
override fun run() {
52+
animations[index] = circles[index].circleAnimation().also { it.start() }
53+
index = if (index == circles.lastIndex) 0 else index + 1
54+
postRunnableAnimation(this)
55+
}
56+
}
57+
3758
private var delay: Long = 0L
3859
private var duration: Long = 0L
3960
private var circleCount: Long = 0L
4061
private var radius: Float = 0f
4162
private var size: Int = 0
4263

43-
private var jobAnimation: Job? = null
44-
private var jobFps : Job? = null
45-
4664
private var state = State.None
4765
set(value) {
4866
field = value
4967
when (value) {
5068
State.Playing -> {
5169
animations.values.forEach { it.end() }
5270
animations.clear()
53-
jobAnimation = animation()
54-
}
55-
State.Stopped -> try {
56-
jobAnimation?.cancel()
57-
jobAnimation = null
58-
} catch (e: UninitializedPropertyAccessException) {
59-
// cancel() was called before start()
71+
postRunnableAnimation(runnableAnimation)
6072
}
73+
State.Stopped -> removeCallbacks(runnableAnimation)
6174
State.None -> Unit
6275
}
6376
}
6477

6578
override fun onAttachedToWindow() {
6679
super.onAttachedToWindow()
67-
jobFps = GlobalScope.launch(Dispatchers.Main) {
68-
while (isActive) {
69-
awaitFrame()
70-
invalidate()
71-
}
72-
}
80+
postRunnableFps(runnableFps, fps)
7381
}
7482

7583
override fun onDetachedFromWindow() {
7684
super.onDetachedFromWindow()
77-
jobFps?.cancel()
78-
jobFps = null
79-
jobAnimation?.cancel()
80-
jobAnimation = null
85+
removeCallbacks(runnableAnimation)
86+
removeCallbacks(runnableFps)
8187
}
8288

89+
@SuppressLint("Recycle")
8390
private fun init(attrs: AttributeSet) {
8491
context.obtainStyledAttributes(attrs, R.styleable.RippleView, 0, 0).also {
85-
val drawable = it.getDrawable(R.styleable.RippleView_drawable)
92+
val drawable = it.getDrawable(R.styleable.RippleView_drawable)!!
8693
delay = it.getInt(R.styleable.RippleView_delay, 500).toLong()
8794
duration = it.getInt(R.styleable.RippleView_duration, 500).toLong()
8895
size = it.getDimensionPixelSize(R.styleable.RippleView_size, 0)
@@ -93,13 +100,19 @@ class RippleView : View {
93100
}.recycle()
94101
}
95102

96-
/** This coroutine generates an animation at each [interval][circleCount]. */
97-
private fun animation(): Job = GlobalScope.launch(Dispatchers.Main) {
98-
var index = 0
99-
while (isActive) {
100-
animations[index] = circles[index].circleAnimation().also { it.start() }
101-
index = if (index == circles.lastIndex) 0 else index + 1
102-
delay(delay)
103+
private fun postRunnableAnimation(runnable: Runnable) {
104+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
105+
postOnAnimationDelayed(runnable, delay)
106+
} else {
107+
postDelayed(runnable, delay)
108+
}
109+
}
110+
111+
private fun postRunnableFps(runnable: Runnable, fps: Long) {
112+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
113+
postOnAnimation(runnable)
114+
} else {
115+
postDelayed(runnable, fps)
103116
}
104117
}
105118

0 commit comments

Comments
 (0)