版本1
调用方式:
private fun testAsyncChain() {
AsyncChain().next(AsyncChain.UI_THREAD_TYPE) {
Toast.makeText(this@MainActivity, "begin", Toast.LENGTH_SHORT).show()
}.next(AsyncChain.WORK_THREAD_TYPE) {
Thread.sleep(1000L)
1
}.next(AsyncChain.UI_THREAD_TYPE) {
Toast.makeText(this@MainActivity, "middle", Toast.LENGTH_SHORT).show()
(it as Int) + 2
}.next(AsyncChain.WORK_THREAD_TYPE) {
Thread.sleep(3000L)
(it as Int) + 3
}.next(AsyncChain.UI_THREAD_TYPE) {
Toast.makeText(this@MainActivity, "end, result: $it", Toast.LENGTH_SHORT).show()
}.start()
}
实现代码:
package com.example.helloworld.tools
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.properties.Delegates
class AsyncChain {
companion object {
const val UI_THREAD_TYPE = 0
const val WORK_THREAD_TYPE = 1
}
private class Task(val threadType: Int, val action: (Any?) -> Any?)
private val lock = Object()
private var cancelled = false
private var lastResult: Any? = null
private val tasks = Collections.synchronizedList(LinkedList<Task>())
private var isExecuting: AtomicBoolean = AtomicBoolean(false)
private val thread = HandlerThread("AsyncChain")
private var workHandler by Delegates.notNull<Handler>()
private val uiHandler = Handler(Looper.getMainLooper())
fun next(threadType: Int, action: (Any?) -> Any?): AsyncChain {
if (isExecuting.get()) {
throw IllegalStateException("tasks are running already!")
}
tasks.add(Task(threadType, action))
return this
}
fun start() {
execute()
}
fun cancel() {
cancelled = true
}
private fun execute() {
if (isExecuting.getAndSet(true)) {
throw IllegalStateException("tasks are running already!")
}
thread.start()
workHandler = Handler(thread.looper)
Thread() {
try {
for (task in tasks) {
if (cancelled) {
break
}
when {
task.threadType == UI_THREAD_TYPE -> uiHandler.post {
lastResult = task.action(lastResult)
synchronized(lock) {
lock.notify()
}
}
task.threadType == WORK_THREAD_TYPE -> workHandler.post {
lastResult = task.action(lastResult)
synchronized(lock) {
lock.notify()
}
}
else -> throw IllegalArgumentException("unknown thread type: ${task.threadType}")
}
synchronized(lock) {
lock.wait()
}
}
} finally {
thread.quit()
}
}.start()
}
}
RxJava直接就能实现(相比之下,代码会稍微多点):
private fun testRxJava() {
val executor = Executors.newSingleThreadExecutor()
val scheduler = Schedulers.from(executor)
Observable
.create<Int> { emitter ->
Toast.makeText(this@MainActivity, "begin", Toast.LENGTH_SHORT).show()
emitter.onNext(0)
emitter.onComplete()
}
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(scheduler)
.map {
Log.v(TAG, "thread: ${Thread.currentThread().name}")
Thread.sleep(1000L)
1
}
.observeOn(AndroidSchedulers.mainThread())
.map {
Toast.makeText(this@MainActivity, "middle", Toast.LENGTH_SHORT).show()
Log.v(TAG, "thread: ${Thread.currentThread().name}")
it + 2
}
.observeOn(scheduler)
.map {
Log.v(TAG, "thread: ${Thread.currentThread().name}")
Thread.sleep(3000L)
it + 3
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe() {
Log.v(TAG, "thread: ${Thread.currentThread().name}")
Toast.makeText(this@MainActivity, "end, result: $it", Toast.LENGTH_SHORT).show()
}
}
版本2
调用方式:
private fun testAsyncChain() {
AsyncChain().next(true, AsyncChain.UI_THREAD_TYPE) { param ->
Toast.makeText(this@MainActivity, "begin", Toast.LENGTH_SHORT).show()
AlertDialog
.Builder(this)
.setTitle("Test")
.setMessage("waiting! confirm to run next task.")
.setPositiveButton("confirm") { _, _ ->
param.confirm()
}
.setNegativeButton("cancel") { _, _ ->
param.cancel()
}
.show()
}.next(AsyncChain.WORK_THREAD_TYPE) {
Thread.sleep(1000L)
1
}.next(AsyncChain.UI_THREAD_TYPE) {
Toast.makeText(this@MainActivity, "middle", Toast.LENGTH_SHORT).show()
(it.lastResult as Int) + 2
}.next(AsyncChain.WORK_THREAD_TYPE) {
Thread.sleep(3000L)
(it.lastResult as Int) + 3
}.next(AsyncChain.UI_THREAD_TYPE) {
Toast.makeText(
this@MainActivity,
"end, last result: ${it.lastResult}",
Toast.LENGTH_SHORT
).show()
}.start()
}
实现代码:
package com.example.helloworld.tools
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.properties.Delegates
class AsyncChain {
companion object {
const val UI_THREAD_TYPE = 0
const val WORK_THREAD_TYPE = 1
}
private class Task(val waitToConfirm: Boolean, val threadType: Int, val action: (Param) -> Any?)
class Param(
var waitToConfirm: Boolean,
var lastResult: Any?,
private val chain: AsyncChain,
private val lock: Object
) {
fun confirm() {
if (waitToConfirm) {
synchronized(lock) {
lock.notify()
}
} else {
// no need to call confirm()
}
}
fun cancel() {
chain.cancel()
if (waitToConfirm) {
synchronized(lock) {
lock.notify()
}
}
}
}
private val lock = Object()
private var param = Param(false, null, this, lock)
private var cancelled = false
private val tasks = Collections.synchronizedList(LinkedList<Task>())
private var isExecuting: AtomicBoolean = AtomicBoolean(false)
private val thread = HandlerThread("AsyncChain")
private var workHandler by Delegates.notNull<Handler>()
private val uiHandler = Handler(Looper.getMainLooper())
fun next(threadType: Int, action: (Param) -> Any?): AsyncChain {
return next(false, threadType, action)
}
fun next(waitToConfirm: Boolean, threadType: Int, action: (Param) -> Any?): AsyncChain {
if (isExecuting.get()) {
throw IllegalStateException("tasks are running already!")
}
tasks.add(Task(waitToConfirm, threadType, action))
return this
}
fun start() {
execute()
}
fun cancel() {
cancelled = true
}
private fun doJob(task: Task) {
param.waitToConfirm = task.waitToConfirm
param.lastResult = task.action(param)
if (!task.waitToConfirm) {
synchronized(lock) {
lock.notify()
}
}
}
private fun execute() {
if (isExecuting.getAndSet(true)) {
throw IllegalStateException("tasks are running already!")
}
thread.start()
workHandler = Handler(thread.looper)
Thread() {
try {
for (task in tasks) {
if (cancelled) {
break
}
when {
task.threadType == UI_THREAD_TYPE -> uiHandler.post {
doJob(task)
}
task.threadType == WORK_THREAD_TYPE -> workHandler.post {
doJob(task)
}
else -> throw IllegalArgumentException("unknown thread type: ${task.threadType}")
}
synchronized(lock) {
lock.wait()
}
}
} finally {
thread.quit()
}
}.start()
}
}
leehong大神在13年实现了一个版本:Android 异步链式调用设计
网友评论