android 链式拉取进程,Android 多个后台任务和 UI 任务串行执行的链式调用设计

版本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())

private var isExecuting: AtomicBoolean = AtomicBoolean(false)

private val thread = HandlerThread("AsyncChain")

private var workHandler by Delegates.notNull()

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 { 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())

private var isExecuting: AtomicBoolean = AtomicBoolean(false)

private val thread = HandlerThread("AsyncChain")

private var workHandler by Delegates.notNull()

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 异步链式调用设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值