android 方法體任務隊列

一、我們會遇到一種情況:

1、點擊某個按鈕或發生某個信息指令,進而執行一個任務(如請求接口)

2、但是!由於快速點擊,或發生信息指令時、短時間內頻繁執行了多次

3、當我們收到某個信息指令時,只需執行一次任務時,代碼邏輯顯得更加雜亂

因此,本文加入了方法體任務隊列概念,不多說,直接上源碼!!

 

二、方法隊列源碼,FunQueueTask

/**
 * 方法體任務隊列
 * 注:
 * offer() :如果BlockingQueue可以容納,則返回true,否則返回false.(本方法不阻塞當前執行方法的線程)
 * poll() :若隊列爲空,返回null(本方法不阻塞當前執行方法的線程)
 * peek() :取出隊頭的元素,並不刪除
 *
 * 1、produceChain與consumeChain需要成對出現
 * 2、produceSingle與consumeSingle需要成對出現
 *
 */
class FunQueueTask<T> {

    //鏈式任務隊列
    private var chainBasket: BlockingQueue<() -> T?> = LinkedBlockingQueue()
    //鏈式任務隊列標記位
    private var flag = true

    //單任務隊列
    private var singleBasket: BlockingQueue<() -> T?> = LinkedBlockingQueue(1)

    //******************************鏈式隊列*************************************************
    fun produceChain(block: () -> T?): Boolean {
        val isSucceed = chainBasket.offer(block)
        YLogUtils.d("鏈式任務--生產", block, "成功?", isSucceed)
        //如果隊列只有一個元素,則立馬出列
        if (flag && isSucceed) {
            flag = false
            val t = chainBasket.poll()
            YLogUtils.d("鏈式任務--隊列只有一個元素,立馬消費", t)
            t?.invoke()
        }
        return isSucceed
    }

    fun consumeChain() {
        val t = chainBasket.poll()
        YLogUtils.d("鏈式任務--消費", t)
        t?.invoke()
        //若方法體隊列已全部出列,則標記爲true
        if (t == null) {
            flag = true
        }
    }

    //*******************************單任務隊列*************************************************
    fun produceSingle(block: () -> T?): Boolean {
        val isSucceed = singleBasket.offer(block)
        YLogUtils.d("單任務--生產", block, "成功?", isSucceed)
        //如果隊列有元素,則立馬取出,但不消費
        if (isSucceed) {
            val t = singleBasket.peek()
            YLogUtils.d("單任務--隊列有元素,取出元素,但不消費", t)
            t?.invoke()
        }
        return isSucceed
    }

    fun consumeSingle() {
        val t = singleBasket.poll()
        YLogUtils.d("單任務-消費", t)
    }
}

三、FunTaskManager,全局管理任務隊列,也可以局部創建FunQueueTask

/**
 * 任務經營者(單例,全局任務)
 */
class FunTaskManager private constructor() {
    //方法體任務隊列
    private val funQueueTask = FunQueueTask<Any>()

    fun getFunQueueTask(): FunQueueTask<Any> {
        return funQueueTask
    }

    private object Holder {
        val instance = FunTaskManager()
    }

    companion object {

        @Synchronized
        fun getInstance(): FunTaskManager {
            return Holder.instance
        }
    }
}

四、simple

/**
 * @Author Administrator
 * @Date 2020/3/12-11:38
 * @TODO mvc 任務隊列請求
 */
class QueueApiSimpleActivity : BaseActivity() {

    companion object {
        fun startAct(context: Context) {
            ActivityUtils.startActivity(context, QueueApiSimpleActivity::class.java)
        }
    }

    private val simpleMode = ApiSimpleModel()

    override fun initLayoutID(): Int = R.layout.simple_api_test_activity_queue

    override fun initUI(savedInstanceState: Bundle?) {

    }

    fun onRequest(view: View) {
        when (view.id) {
            R.id.requestData_common -> {
                for (i in 1..10) {
                    sendGiftCommon(SendGiftVo("123", "456", 1, 100, 0))
                }
            }
            R.id.requestData_fun_single -> {
                for (i in 1..10) {
                    FunTaskManager.getInstance().getFunQueueTask().produceSingle {
                        sendGiftFunSingle(SendGiftVo("123", "456", 1, 100, 0))
                    }
                }
            }
            R.id.requestData_fun_chain -> {
                for (i in 1..10) {
                    FunTaskManager.getInstance().getFunQueueTask().produceChain {
                        sendGiftFunChain(SendGiftVo("123", "456", 1, 100, 0))
                    }
                }
            }
        }
    }


    /**
     * 普通請求
     */
    private fun sendGiftCommon(sendGiftVo: SendGiftVo) {
        simpleMode.sendGift(RxObserver(doNext = { it ->
            tv_msg.setText(it.msg)
        }, doError = { _, _ ->
        }), lifecycleProvider, sendGiftVo)
    }

    /**
     * 單任務隊列
     */
    private fun sendGiftFunSingle(sendGiftVo: SendGiftVo) {
        simpleMode.sendGift(RxObserver(doNext = { it ->
            tv_msg.setText(it.msg)
            FunTaskManager.getInstance().getFunQueueTask().consumeSingle()
        }, doError = { _, _ ->
            FunTaskManager.getInstance().getFunQueueTask().consumeSingle()
        }), lifecycleProvider, sendGiftVo)
    }

    /**
     * 鏈式隊列
     */
    private fun sendGiftFunChain(sendGiftVo: SendGiftVo) {
        simpleMode.sendGift(RxObserver(doNext = { it ->
            tv_msg.setText(it.msg)
            FunTaskManager.getInstance().getFunQueueTask().consumeChain()
        }, doError = { _, _ ->
            FunTaskManager.getInstance().getFunQueueTask().consumeChain()
        }), lifecycleProvider, sendGiftVo)
    }
}

五、測試結果

     5.1、普通請求結果

  • 提交多次請求任務,交由網絡框架的線程池隊列逐一執行任務

 

    5.2.單任務隊列

  • 提交多次請求任務,若任務已存在,未出列,則只執行一次任務

 

    5.3、鏈式隊列

  • 提交多次請求任務,每次只執行一個任務,執行完當前任務後,再執行下一個任務,直到所有任務出列

 

github地址 YLibrary

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章