aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2018-12-24 20:05:06 -0500
committerGitHub <noreply@github.com>2018-12-24 20:05:06 -0500
commit8447b1ae8ce89b3f1bbe79dbae8847d901831c12 (patch)
treece516950e452581766e905ead32970d891bb46f6 /core
parent701b94ab09ff53aca682fac6c4ef5364566339be (diff)
downloadkau-8447b1ae8ce89b3f1bbe79dbae8847d901831c12.tar.gz
kau-8447b1ae8ce89b3f1bbe79dbae8847d901831c12.tar.bz2
kau-8447b1ae8ce89b3f1bbe79dbae8847d901831c12.zip
Enhancement/coroutines (#180)
* Add coroutine dependency * Add coroutines to kprefactivity * Change base job to supervisor * Update coroutines for faq * Update changelog * Use preloading in media picker core * Make test logging internal * Remove anko
Diffstat (limited to 'core')
-rw-r--r--core/README.md4
-rw-r--r--core/build.gradle4
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt30
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt105
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt7
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt13
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt55
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt27
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt3
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt21
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt71
-rw-r--r--core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt83
12 files changed, 175 insertions, 248 deletions
diff --git a/core/README.md b/core/README.md
index 39899dd..b9a10f5 100644
--- a/core/README.md
+++ b/core/README.md
@@ -131,6 +131,9 @@ These variants are weakly held in the private `KotterknifeRegistry` object, and
values through the `Kotterknife.reset` method. This is typically useful for Fragments, as they do not follow
the same lifecycle as Activities and Views.
+Note that this is useful for views that have ids in multiple layout files or in `id.xml` files.
+Kotlin has another solution, [`kotlin-android-extensions`](https://kotlinlang.org/docs/tutorials/android-plugin.html), which is more convenient.
+
## Ripple Canvas
Ripple canvas provides a way to create simultaneous ripples against a background color.
@@ -210,7 +213,6 @@ Include your email and subject, along with other optional configurations such as
## Extension Functions
> "[Extensions](https://kotlinlang.org/docs/reference/extensions.html) provide the ability to extend a class with new functionality without having to inherit from the class"
-<br/>Note that since KAU depends on [ANKO](https://github.com/Kotlin/anko), all of the extensions in its core package is also in KAU.
KAU's vast collection of extensions is one of its strongest features.
There are too many to explain here, but you may check out the [utils package](https://github.com/AllanWang/KAU/tree/master/core/src/main/kotlin/ca/allanwang/kau/utils)
diff --git a/core/build.gradle b/core/build.gradle
index a57ee6e..3ac4f36 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -11,12 +11,12 @@ dependencies {
api "androidx.constraintlayout:constraintlayout:${kau.constraintLayout}"
api "com.google.android.material:material:${kau.googleMaterial}"
+ api "org.jetbrains.kotlinx:kotlinx-coroutines-android:${kau.coroutines}"
+
api "com.mikepenz:iconics-core:${kau.iconics}@aar"
api "com.mikepenz:google-material-typeface:${kau.iconicsGoogle}.original@aar"
api "com.afollestad.material-dialogs:core:${kau.materialDialog}"
-
- api "org.jetbrains.anko:anko-commons:${kau.anko}"
}
apply from: '../artifacts.gradle'
diff --git a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt
index 85e711b..bf977f2 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/internal/KauBaseActivity.kt
@@ -15,8 +15,14 @@
*/
package ca.allanwang.kau.internal
+import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlin.coroutines.CoroutineContext
/**
* Created by Allan Wang on 2017-08-01.
@@ -26,11 +32,31 @@ import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult
* Ensures that some singleton methods are called.
* This is simply a convenience class;
* you can always copy and paste this to your own class.
+ *
+ * This also implements [CoroutineScope] that adheres to the activity lifecycle.
+ * Note that by default, [SupervisorJob] is used, to avoid exceptions in one child from affecting that of another.
+ * The default job can be overridden within [defaultJob]
*/
-abstract class KauBaseActivity : AppCompatActivity() {
+abstract class KauBaseActivity : AppCompatActivity(), CoroutineScope {
+
+ open lateinit var job: Job
+ override val coroutineContext: CoroutineContext
+ get() = Dispatchers.Main + job
+
+ open fun defaultJob(): Job = SupervisorJob()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ job = defaultJob()
+ }
+
+ override fun onDestroy() {
+ job.cancel()
+ super.onDestroy()
+ }
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
kauOnRequestPermissionsResult(permissions, grantResults)
}
-}
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt
deleted file mode 100644
index b767b30..0000000
--- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Zip.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ca.allanwang.kau.kotlin
-
-import org.jetbrains.anko.doAsync
-import java.util.concurrent.atomic.AtomicInteger
-
-/**
- * Created by Allan Wang on 2017-08-06.
- *
- * Collection of zip methods that aim to replicate
- * <a href="http://reactivex.io/documentation/operators/zip.html">Reactive Zips</a>
- * For unit returning functions
- *
- * Typically, the functions will execute asynchronously and call their given callbacks when finished.
- * Once all callbacks are called, the final onFinish callback will be executed.
- *
- * There is also a helper zipper to wrap synchronous functions with Anko's doAsync to achieve the same results
- *
- * Note that not wrapping synchronous functions will render these methods useless,
- * as you can simply define an inline callback after all functions are finished
- */
-
-/**
- * Callback which will only execute the first time
- */
-open class ZipCallbackBase {
- var completed: Boolean = false
-
- inline operator fun invoke(callback: () -> Unit) {
- if (completed) return
- completed = true
- callback()
- }
-}
-
-class ZipCallback<T>(val onReceived: (T) -> Unit) : ZipCallbackBase() {
- operator fun invoke(result: T) = invoke { onReceived(result) }
-}
-
-class ZipEmptyCallback(val onReceived: () -> Unit) : ZipCallbackBase() {
- operator fun invoke() = invoke(onReceived)
-}
-
-/**
- * Given a default result, a series of tasks, and a finished callback,
- * this method will run all tasks and wait until all tasks emit a response
- * The response will then be sent back to the callback
- *
- * ALl tasks must invoke the task callback for [onFinished] to execute
- */
-inline fun <reified T> Collection<(ZipCallback<T>) -> Unit>.zip(
- defaultResult: T,
- crossinline onFinished: (results: Array<T>) -> Unit
-) {
- val result = Array(size) { defaultResult }
- val countDown = AtomicInteger(size)
- forEachIndexed { index, asyncFun ->
- asyncFun(ZipCallback {
- result[index] = it
- if (countDown.decrementAndGet() <= 0)
- onFinished(result)
- })
- }
-}
-
-/**
- * Simplified zip method with no finished callback arguments
- */
-inline fun Collection<(ZipEmptyCallback) -> Unit>.zip(crossinline onFinished: () -> Unit) {
- val countDown = AtomicInteger(size)
- forEach { asyncFun ->
- asyncFun(ZipEmptyCallback {
- if (countDown.decrementAndGet() <= 0)
- onFinished()
- })
- }
-}
-
-/**
- * Converts a collection of synchronous tasks to asynchronous tasks with a common callback
- */
-inline fun Collection<() -> Unit>.zipAsync(crossinline onFinished: () -> Unit) {
- map { synchronousFun ->
- { callback: ZipEmptyCallback ->
- doAsync {
- synchronousFun()
- callback()
- }; Unit
- }
- }.zip(onFinished)
-}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
index f92edb3..52e5415 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/logging/KL.kt
@@ -22,4 +22,9 @@ import ca.allanwang.kau.BuildConfig
*
* Internal KAU logger
*/
-object KL : KauLogger("KAU", { BuildConfig.DEBUG })
+object KL : KauLogger("KAU", { BuildConfig.DEBUG }) {
+ internal inline fun test(message: () -> Any?) {
+ if (BuildConfig.DEBUG)
+ d { "Test1234 ${message()}" }
+ }
+}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt
index a655e5b..3dd4bb9 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ActivityUtils.kt
@@ -28,13 +28,13 @@ import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.View
+import android.view.ViewGroup
import androidx.annotation.ColorInt
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import ca.allanwang.kau.R
import com.google.android.material.snackbar.Snackbar
import com.mikepenz.iconics.typeface.IIcon
-import org.jetbrains.anko.contentView
/**
* Created by Allan Wang on 2017-06-21.
@@ -160,6 +160,17 @@ inline fun Activity.showKeyboard() {
currentFocus?.showKeyboard()
}
+/**
+ * Gets the view set by [Activity.setContentView] if it exists.
+ *
+ * Taken courtesy of <a href="https://github.com/Kotlin/anko">Anko</a>
+ *
+ * Previously, Anko was a dependency in KAU, but has been removed on 12/24/2018
+ * as most of the methods weren't used
+ */
+inline val Activity.contentView: View?
+ get() = (findViewById(android.R.id.content) as? ViewGroup)?.getChildAt(0)
+
inline fun Activity.snackbar(
text: String,
duration: Int = Snackbar.LENGTH_LONG,
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
index 314ca60..5b4b188 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/BundleUtils.kt
@@ -20,10 +20,12 @@ import android.app.Activity
import android.app.ActivityOptions
import android.content.Context
import android.os.Bundle
+import android.os.Parcelable
import android.util.Pair
import android.view.View
import androidx.annotation.AnimRes
import ca.allanwang.kau.R
+import java.io.Serializable
/**
* Created by Allan Wang on 10/12/17.
@@ -37,6 +39,56 @@ infix fun Bundle.with(bundle: Bundle?): Bundle {
}
/**
+ * Saves all bundle args based on their respective types.
+ *
+ * Taken courtesy of <a href="https://github.com/Kotlin/anko">Anko</a>
+ *
+ * Previously, Anko was a dependency in KAU, but has been removed on 12/24/2018
+ * as most of the methods weren't used
+ */
+fun bundleOf(vararg params: kotlin.Pair<String, Any?>): Bundle {
+ val b = Bundle()
+ for (p in params) {
+ val (k, v) = p
+ when (v) {
+ null -> b.putSerializable(k, null)
+ is Boolean -> b.putBoolean(k, v)
+ is Byte -> b.putByte(k, v)
+ is Char -> b.putChar(k, v)
+ is Short -> b.putShort(k, v)
+ is Int -> b.putInt(k, v)
+ is Long -> b.putLong(k, v)
+ is Float -> b.putFloat(k, v)
+ is Double -> b.putDouble(k, v)
+ is String -> b.putString(k, v)
+ is CharSequence -> b.putCharSequence(k, v)
+ is Parcelable -> b.putParcelable(k, v)
+ is Serializable -> b.putSerializable(k, v)
+ is BooleanArray -> b.putBooleanArray(k, v)
+ is ByteArray -> b.putByteArray(k, v)
+ is CharArray -> b.putCharArray(k, v)
+ is DoubleArray -> b.putDoubleArray(k, v)
+ is FloatArray -> b.putFloatArray(k, v)
+ is IntArray -> b.putIntArray(k, v)
+ is LongArray -> b.putLongArray(k, v)
+ is Array<*> -> {
+ @Suppress("UNCHECKED_CAST")
+ when {
+ v.isArrayOf<Parcelable>() -> b.putParcelableArray(k, v as Array<out Parcelable>)
+ v.isArrayOf<CharSequence>() -> b.putCharSequenceArray(k, v as Array<out CharSequence>)
+ v.isArrayOf<String>() -> b.putStringArray(k, v as Array<out String>)
+ else -> throw KauException("Unsupported bundle component (${v.javaClass})")
+ }
+ }
+ is ShortArray -> b.putShortArray(k, v)
+ is Bundle -> b.putBundle(k, v)
+ else -> throw KauException("Unsupported bundle component (${v.javaClass})")
+ }
+ }
+ return b
+}
+
+/**
* Adds transition bundle if context is activity and build is lollipop+
*/
@SuppressLint("NewApi")
@@ -62,7 +114,8 @@ fun Bundle.withSceneTransitionAnimation(parent: View, data: Map<Int, String>) =
@SuppressLint("NewApi")
fun Bundle.withSceneTransitionAnimation(context: Context, data: Map<View, String>) {
if (context !is Activity || !buildIsLollipopAndUp) return
- val options = ActivityOptions.makeSceneTransitionAnimation(context,
+ val options = ActivityOptions.makeSceneTransitionAnimation(
+ context,
*data.map { (view, tag) -> Pair(view, tag) }.toTypedArray()
)
putAll(options.toBundle())
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
index 134126d..60ef236 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ContextUtils.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Allan Wang
+ * Copyright 2017 Allan Wang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,8 @@ import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
import android.util.TypedValue
import android.view.View
import android.view.animation.AnimationUtils
@@ -45,10 +47,33 @@ import androidx.core.content.ContextCompat
import ca.allanwang.kau.R
import ca.allanwang.kau.logging.KL
import com.afollestad.materialdialogs.MaterialDialog
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlin.coroutines.CoroutineContext
/**
* Created by Allan Wang on 2017-06-03.
*/
+private object ContextHelper: CoroutineScope {
+
+ val handler = Handler(Looper.getMainLooper())
+
+ override val coroutineContext: CoroutineContext
+ get() = Dispatchers.Main
+}
+
+/**
+ * Most context items implement [CoroutineScope] by default.
+ * We will add a fallback just in case.
+ * It is expected that the scope returned always has the Android main dispatcher as part of the context.
+ */
+internal inline val Context.ctxCoroutine: CoroutineScope
+ get() = this as? CoroutineScope ?: ContextHelper
+
+fun Context.runOnUiThread(f: Context.() -> Unit) {
+ if (Looper.getMainLooper() === Looper.myLooper()) f() else ContextHelper.handler.post { f() }
+}
/**
* Helper class to launch an activity from a context
diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt
index 1c97900..75dc1c1 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/utils/FragmentUtils.kt
@@ -16,12 +16,11 @@
package ca.allanwang.kau.utils
import androidx.fragment.app.Fragment
-import org.jetbrains.anko.bundleOf
/**
* Created by Allan Wang on 2017-07-02.
*/
-fun <T : Fragment> T.withArguments(vararg params: Pair<String, Any>): T {
+fun <T : Fragment> T.withArguments(vararg params: Pair<String, Any?>): T {
arguments = bundleOf(*params)
return this
}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt
index 6a75aa9..51e63f9 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/xml/Changelog.kt
@@ -26,11 +26,12 @@ import androidx.annotation.LayoutRes
import androidx.annotation.XmlRes
import androidx.recyclerview.widget.RecyclerView
import ca.allanwang.kau.R
+import ca.allanwang.kau.utils.ctxCoroutine
import ca.allanwang.kau.utils.materialDialog
import ca.allanwang.kau.utils.use
import com.afollestad.materialdialogs.MaterialDialog
-import org.jetbrains.anko.doAsync
-import org.jetbrains.anko.uiThread
+import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
import org.xmlpull.v1.XmlPullParser
/**
@@ -39,15 +40,13 @@ import org.xmlpull.v1.XmlPullParser
* Easy changelog loader
*/
fun Context.showChangelog(@XmlRes xmlRes: Int, @ColorInt textColor: Int? = null, customize: MaterialDialog.Builder.() -> Unit = {}) {
- doAsync {
- val items = parse(this@showChangelog, xmlRes)
- uiThread {
- materialDialog {
- title(R.string.kau_changelog)
- positiveText(R.string.kau_great)
- adapter(ChangelogAdapter(items, textColor), null)
- customize()
- }
+ ctxCoroutine.launch {
+ val items = async { parse(this@showChangelog, xmlRes) }.await()
+ materialDialog {
+ title(R.string.kau_changelog)
+ positiveText(R.string.kau_great)
+ adapter(ChangelogAdapter(items, textColor), null)
+ customize()
}
}
}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt
index cb57216..73d7d6c 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/xml/FAQ.kt
@@ -21,8 +21,6 @@ import android.text.Html
import android.text.Spanned
import androidx.annotation.XmlRes
import ca.allanwang.kau.utils.use
-import org.jetbrains.anko.doAsync
-import org.jetbrains.anko.uiThread
import org.xmlpull.v1.XmlPullParser
/**
@@ -30,8 +28,8 @@ import org.xmlpull.v1.XmlPullParser
*/
/**
- * Parse an xml asynchronously with two tags, <question>Text</question> and <answer>Text</answer>,
- * and invoke the [callback] on the ui thread
+ * Parse an xml asynchronously with two tags, <question>Text</question> and <answer>Text</answer>.
+ * Note that this should executed in a background thread.
*/
@Suppress("DEPRECATION")
fun Context.kauParseFaq(
@@ -39,47 +37,44 @@ fun Context.kauParseFaq(
/**
* If \n is used, it will automatically be converted to </br>
*/
- parseNewLine: Boolean = true,
- callback: (items: List<FaqItem>) -> Unit
-) {
- doAsync {
- val items = mutableListOf<FaqItem>()
- resources.getXml(xmlRes).use { parser: XmlResourceParser ->
- var eventType = parser.eventType
- var question: Spanned? = null
- var flag = -1 //-1, 0, 1 -> invalid, question, answer
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlPullParser.START_TAG) {
- flag = when (parser.name) {
- "question" -> 0
- "answer" -> 1
- else -> -1
+ parseNewLine: Boolean = true
+): List<FaqItem> {
+ val items = mutableListOf<FaqItem>()
+ resources.getXml(xmlRes).use { parser: XmlResourceParser ->
+ var eventType = parser.eventType
+ var question: Spanned? = null
+ var flag = -1 //-1, 0, 1 -> invalid, question, answer
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ flag = when (parser.name) {
+ "question" -> 0
+ "answer" -> 1
+ else -> -1
+ }
+ } else if (eventType == XmlPullParser.TEXT) {
+ when (flag) {
+ 0 -> {
+ question = Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "<br/>" else ""))
+ flag = -1
}
- } else if (eventType == XmlPullParser.TEXT) {
- when (flag) {
- 0 -> {
- question = Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "<br/>" else ""))
- flag = -1
- }
- 1 -> {
- items.add(
- FaqItem(
- items.size + 1,
- question
- ?: throw IllegalArgumentException("KAU FAQ answer found without a question"),
- Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "<br/>" else ""))
- )
+ 1 -> {
+ items.add(
+ FaqItem(
+ items.size + 1,
+ question
+ ?: throw IllegalArgumentException("KAU FAQ answer found without a question"),
+ Html.fromHtml(parser.text.replace("\n", if (parseNewLine) "<br/>" else ""))
)
- question = null
- flag = -1
- }
+ )
+ question = null
+ flag = -1
}
}
- eventType = parser.next()
}
+ eventType = parser.next()
}
- uiThread { callback(items) }
}
+ return items
}
data class FaqItem(val number: Int, val question: Spanned, val answer: Spanned)
diff --git a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt b/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt
deleted file mode 100644
index 1fbc38f..0000000
--- a/core/src/test/kotlin/ca/allanwang/kau/kotlin/ZipTest.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2018 Allan Wang
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package ca.allanwang.kau.kotlin
-
-import org.jetbrains.anko.doAsync
-import org.junit.Test
-import java.util.Random
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-import kotlin.test.assertTrue
-
-/**
- * Created by Allan Wang on 2017-08-06.
- */
-class ZipTest {
-
- val debug = false
-
- fun p(text: String) {
- if (debug) println(text)
- }
-
- @Test
- fun basic() {
- val start = System.currentTimeMillis()
- val latch = CountDownLatch(1)
- val rnd = Random()
- (0..10).map {
- { callback: ZipCallback<Int> ->
- doAsync {
- val sleepTime = rnd.nextInt(100) + 200L
- p("Task $it will sleep for ${sleepTime}ms")
- Thread.sleep(sleepTime)
- val finish = System.currentTimeMillis()
- p("Task $it finished in ${finish - start}ms at $finish")
- callback(it)
- }; Unit
- }
- }.zip(-1) { results ->
- val finish = System.currentTimeMillis()
- println("Results ${results.contentToString()} received in ${finish - start}ms at $finish")
- assertTrue((0..10).toList().toTypedArray().contentEquals(results), "Basic zip results do not match")
- assertTrue(finish - start < 1000L, "Basic zip does not seem to be running asynchronously")
- latch.countDown()
- }
- latch.await(1100, TimeUnit.MILLISECONDS)
- }
-
- @Test
- fun basicAsync() {
- val start = System.currentTimeMillis()
- val latch = CountDownLatch(1)
- val rnd = Random()
- (0..10).map {
- {
- val sleepTime = rnd.nextInt(100) + 200L
- p("Task $it will sleep for ${sleepTime}ms")
- Thread.sleep(sleepTime)
- val finish = System.currentTimeMillis()
- p("Task $it finished in ${finish - start}ms at $finish")
- }
- }.zipAsync {
- val finish = System.currentTimeMillis()
- println("Results received in ${finish - start}ms at $finish")
- assertTrue(finish - start < 1000L, "BasicAsync does not seem to be wrapping the tasks asynchronously")
- latch.countDown()
- }
- latch.await(1100, TimeUnit.MILLISECONDS)
- }
-}