最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android如何使用Flow封裝一個FlowBus工具類

 更新時間:2024年09月24日 12:02:59   作者:淡淡的香煙  
本文介紹了如何在Android中使用Flow封裝一個FlowBus工具類,以替代EvenutBus、Rxbus、LiveDataBus、LiveData等第三方依賴包,作者提供了在Activity、Fragment、Service和Websock中使用FlowBus的具體代碼,并解釋了實現(xiàn)的效果,文章最后還提供了項目demo源碼的下載鏈接

Android中使用Flow封裝一個FlowBus工具類

? 做過Android的同學(xué)應(yīng)該都使用過EvenutBus、Rxbus、LiveDataBus、LiveData等,這些第三方不僅要導(dǎo)入依賴包,而且還要注冊和取消注冊,使用起來非常麻煩,稍不注意就導(dǎo)致內(nèi)存泄漏,自從接觸了Flow、SharedFlow之后感覺使用起來方便多了,于是產(chǎn)生了一個封裝通用事件工具類的想法,直接上代碼.

1.FlowBus:

/**
 * @auth: njb
 * @date: 2024/7/18 10:17
 * @desc: 基于Flow封裝的FlowBus
 */
object FlowBus {
    private const val TAG = "FlowBus"
    private val busMap = mutableMapOf<String, FlowEventBus<*>>()
    private val busStickMap = mutableMapOf<String, FlowStickEventBus<*>>()
    @Synchronized
    fun <T> with(key: String): FlowEventBus<T> {
        var flowEventBus = busMap[key]
        if (flowEventBus == null) {
            flowEventBus = FlowEventBus<T>(key)
            busMap[key] = flowEventBus
        }
        return flowEventBus as FlowEventBus<T>
    }
    @Synchronized
    fun <T> withStick(key: String): FlowStickEventBus<T> {
        var stickEventBus = busStickMap[key]
        if (stickEventBus == null) {
            stickEventBus = FlowStickEventBus<T>(key)
            busStickMap[key] = stickEventBus
        }
        return stickEventBus as FlowStickEventBus<T>
    }
    open class FlowEventBus<T>(private val key: String) : DefaultLifecycleObserver {
        //私有對象用于發(fā)送消息
        private val _events: MutableSharedFlow<T> by lazy {
            obtainEvent()
        }
        //暴露的公有對象用于接收消息
        private val events = _events.asSharedFlow()
        open fun obtainEvent(): MutableSharedFlow<T> =
            MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)
        //在主線程中接收數(shù)據(jù)
        fun register(lifecycleOwner: LifecycleOwner,action: (t: T) -> Unit){
            lifecycleOwner.lifecycleScope.launch {
                events.collect {
                    try {
                        action(it)
                    }catch (e:Exception){
                        e.printStackTrace()
                        Log.e(TAG, "FlowBus - Error:$e")
                    }
                }
            }
        }
        //在協(xié)程中接收數(shù)據(jù)
        fun register(scope: CoroutineScope,action: (t: T) -> Unit){
            scope.launch {
                events.collect{
                    try {
                       action(it)
                    }catch (e:Exception){
                        e.printStackTrace()
                        Log.e(TAG, "FlowBus - Error:$e")
                    }
                }
            }
        }
        //在協(xié)程中發(fā)送數(shù)據(jù)
        suspend fun post(event: T){
            _events.emit(event)
        }
        //在主線程中發(fā)送數(shù)據(jù)
        fun post(scope: CoroutineScope,event: T){
            scope.launch {
                _events.emit(event)
            }
        }
        override fun onDestroy(owner: LifecycleOwner) {
            super.onDestroy(owner)
            Log.w(TAG, "FlowBus ==== 自動onDestroy")
            val subscriptCount = _events.subscriptionCount.value
            if (subscriptCount <= 0)
                busMap.remove(key)
        }
        // 手動調(diào)用的銷毀方法,用于Service、廣播等
        fun destroy() {
            Log.w(TAG, "FlowBus ==== 手動銷毀")
            val subscriptionCount = _events.subscriptionCount.value
            if (subscriptionCount <= 0) {
                busMap.remove(key)
            }
        }
    }
    class FlowStickEventBus<T>(key: String) : FlowEventBus<T>(key) {
        override fun obtainEvent(): MutableSharedFlow<T> =
            MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)
    }
}

2.在Activity中的使用:

2.1傳遞參數(shù)給主界面Activity:

/**
 * @auth: njb
 * @date: 2024/9/10 23:49
 * @desc: 描述
 */
class TestActivity :AppCompatActivity(){
    private val textView:TextView by lazy { findViewById(R.id.tv_test) }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
        initFlowBus()
    }
    private fun initFlowBus() {
        val messageEvent = MessageEvent()
        messageEvent.message = "stop"
        messageEvent.state = false
        textView.setOnClickListener {
            lifecycleScope.launch {
                FlowBus.with<MessageEvent>("test").post(this, messageEvent)
                finish()
            }
        }
    }
}

2.2 MainActivity接收:

/**
 * 初始化
 */
private fun initView() {
    binding.rvWallpaper.apply {
        layoutManager = GridLayoutManager(this@MainActivity, 2)
        adapter = wallPaperAdapter
    }
    binding.btnGetWallpaper.setOnClickListener {
        lifecycleScope.launch {
            mainViewModel.mainIntentChannel.send(MainIntent.GetWallpaper)
        }
        val intent = Intent(this@MainActivity,TestActivity::class.java)
        startActivity(intent)
    }
    FlowBus.with<MessageEvent>("test").register(this@MainActivity) {
        LogUtils.d(TAG,it.toString())
        if(it.message == "stop"){
            LogUtils.d(TAG,"===接收到的消息為==="+it.message)
        }
    }
    FlowBus.with<MessageEvent>("mineFragment").register(this@MainActivity) {
        LogUtils.d(TAG,it.toString())
        if(it.message == "onMine"){
            LogUtils.d(TAG,"===接收到的消息為1111==="+it.message)
        }
    }
}

3.在Fragment中的使用:

3.1 發(fā)送數(shù)據(jù)

package com.cloud.flowbusdemo.fragment
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.cloud.flowbusdemo.databinding.FragmentMineBinding
import com.cloud.flowbusdemo.flow.FlowBus
import com.cloud.flowbusdemo.model.MessageEvent
import kotlinx.coroutines.launch
private const val ARG_PARAM_NAME = "name"
private const val ARG_PARAM_AGE = "age"
/**
 * @auth: njb
 * @date: 2024/9/17 19:43
 * @desc: 描述
 */
class MineFragment :Fragment(){
    private lateinit var binding: FragmentMineBinding
    private val TAG = "MineFragment"
    private var name: String? = null
    private var age: Int? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            name = it.getString(ARG_PARAM_NAME)
            age = it.getInt(ARG_PARAM_AGE)
        }
        Log.i(TAG, "MainFragment 傳遞到 MineFragment 的參數(shù)為 name = $name , age = $age")
        Log.d(TAG, "姓名:" + name + "年齡:" + age)
    }
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentMineBinding.inflate(layoutInflater)
        initView()
        return binding.root
    }
    private fun initView() {
        val messageEvent = MessageEvent()
        messageEvent.message = "onMine"
        messageEvent.state = false
        binding.let {
            it.tvTitle.text = name
            it.tvAge.text  = age.toString()
            it.tvTitle.setOnClickListener {
                lifecycleScope.launch {
                    FlowBus.with<MessageEvent>("mineFragment").post(this, messageEvent)
                }
            }
        }
    }
}

3.2 接收數(shù)據(jù):

private fun initView() {
    binding.rvWallpaper.apply {
        layoutManager = GridLayoutManager(this@MainActivity, 2)
        adapter = wallPaperAdapter
    }
    binding.btnGetWallpaper.setOnClickListener {
        lifecycleScope.launch {
            mainViewModel.mainIntentChannel.send(MainIntent.GetWallpaper)
        }
        val intent = Intent(this@MainActivity,TestActivity::class.java)
        startActivity(intent)
    }
    FlowBus.with<MessageEvent>("test").register(this@MainActivity) {
        LogUtils.d(TAG,it.toString())
        if(it.message == "stop"){
            LogUtils.d(TAG,"===接收到的消息為==="+it.message)
        }
    }
    FlowBus.with<MessageEvent>("mineFragment").register(this@MainActivity) {
        LogUtils.d(TAG,it.toString())
        if(it.message == "onMine"){
            LogUtils.d(TAG,"===接收到的消息為1111==="+it.message)
        }
    }
}

4.在Service中的使用:

4.1發(fā)送數(shù)據(jù):

private fun initService() {
    val intent = Intent(this@MainActivity, FlowBusTestService::class.java)
    intent.putExtra("sockUrl","")
    startService(intent)
}

4.2接收數(shù)據(jù):

/**
 * @auth: njb
 * @date: 2024/9/22 23:32
 * @desc: 描述
 */
class FlowBusTestService:Service() {
    private var sock5Url:String ?= null
    private val TAG = "FlowBusTestService"
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        intent?.let {
            this.sock5Url = intent.getStringExtra("sockUrl")
            LogUtils.d(TAG,"====收到的ip為==="+this.sock5Url)
        }
        return if (intent?.action == Constants.ACTION_DISCONNECT) {
            disconnect()
            START_NOT_STICKY
        } else {
            connect()
            START_STICKY
        }
    }
    private fun connect() {
    }
    private fun disconnect() {
    }
}

5.在Websock中的使用:

5.1發(fā)送數(shù)據(jù):

private fun connectWebSocket() {
    LogUtils.e(TAG, "===connectUrl===$currentWebSocketUrl")
    try {
        if (mWebSocketManager == null) {
            return
        }
        mWebSocketManager?.addListener(object : SocketListener {
            override fun onConnected() {
                LogUtils.e(TAG, "===連接成功====")
                val messageEvent = MessageEvent()
                messageEvent.message = "socket連接成功"
                FloatWindowManager.log("socket連接成功")
                CoroutineScope(Dispatchers.Main).launch{
                    FlowBus.with<MessageEvent>("onConnected").post(this,messageEvent)
                }
            }
            override fun onConnectFailed(throwable: Throwable) {
                LogUtils.e(TAG, "===連接失敗====")
                val messageEvent = MessageEvent()
                messageEvent.message = "socket連接失敗:$currentWebSocketUrl"
                FloatWindowManager.log("socket連接失敗")
            }
            override fun onDisconnect() {
                LogUtils.e(TAG, "===斷開連接====")
                val messageEvent = MessageEvent()
                messageEvent.message = "socket斷開連接"
                FloatWindowManager.log("socket斷開連接")
            }
            override fun onSendDataError(errorResponse: ErrorResponse) {
                LogUtils.e(TAG + "===發(fā)送數(shù)據(jù)失敗====" + errorResponse.description)
                val messageEvent = MessageEvent()
                messageEvent.message = "發(fā)送數(shù)據(jù)失敗--->" + errorResponse.description
                FloatWindowManager.log("發(fā)送數(shù)據(jù)失敗")
            }
            override fun <T> onMessage(msg: String, t: T) {
                LogUtils.e(TAG,"===接收到消息 String===$msg")
                val messageEvent = MessageEvent()
                messageEvent.message = msg
                FloatWindowManager.log("===接收到消息===$msg")
                taskManager?.onHandleMsg(msg)
            }
            override fun <T> onMessage(bytes: ByteBuffer, t: T) {
                LogUtils.e(TAG, "===接收到消息byteBuffer===="+GsonUtils.toJson(bytes))
                val rBuffer = ByteBuffer.allocate(1024)
                val charset = Charset.forName("UTF-8")
                try {
                    val receiveText =
                        charset.newDecoder().decode(rBuffer.asReadOnlyBuffer()).toString()
                    LogUtils.e(TAG, "===接收到消息byteBuffer====$receiveText")
                    val messageEvent = MessageEvent()
                    messageEvent.message = receiveText
                   // FloatWindowManager.log("===收到消息 byte===$receiveText")
                } catch (e: CharacterCodingException) {
                    throw RuntimeException(e)
                }
            }
            override fun onPing(pingData: Framedata) {
                LogUtils.e(TAG, "===心跳onPing===$pingData")
            }
            override fun onPong(framedata: Framedata) {
                LogUtils.e(TAG, "===心跳onPong===$framedata")
                val messageEvent = MessageEvent()
                messageEvent.message = format.format(Date()) + "  | 心跳onPong->"
                FloatWindowManager.log("===心跳onPong===${format.format(Date())}${"->"}$currentWebSocketUrl")
            }
        })
        mWebSocketManager?.start()
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

5.2接收數(shù)據(jù):

private fun initFlowBus() {
    FlowBus.with<MessageEvent>("onConnected").register(this@MainActivity) {
        LogUtils.d(TAG, "收到消息為:$it")
    }
    FlowBus.with<MessageEvent>("onStartVpn").register(this@MainActivity) {
        LogUtils.d(TAG, "收到vpn消息為:$it")
        CoroutineScope(Dispatchers.Main).launch {
            if (it.message == "start" && it.state && Constants.SWITCH_IP) {
                this@MainActivity.sockUrl = it.sockUrl
                LogUtils.d(TAG, "收到代理地址為:${it.sockUrl}")
                AppUtils.prepareVpn(this@MainActivity,it.sockUrl)
               // prepareVpn()
            }
        }
    }
    FlowBus.with<MessageEvent>("onStopVpn").register(this@MainActivity) {
        LogUtils.d(TAG, "收到vpn消息為:$it")
        if (it.message == "stop" && !it.state) {
            AppUtils.stopVpn(this@MainActivity)
        }
    }
}

6.實現(xiàn)的效果如下:

7.項目demo源碼如下:

https://gitee.com/jackning_admin/flowbus-demo

到此這篇關(guān)于Android使用Flow封裝一個FlowBus工具類的文章就介紹到這了,更多相關(guān)Android FlowBus工具類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • android studio集成unity導(dǎo)出工程的實現(xiàn)

    android studio集成unity導(dǎo)出工程的實現(xiàn)

    本文主要介紹了android studio集成unity導(dǎo)出工程的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 5步學(xué)會使用VideoView播放視頻

    5步學(xué)會使用VideoView播放視頻

    這篇文章主要為大家詳細(xì)介紹了5步學(xué)會使用VideoView播放視頻的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Android Notification通知使用詳解

    Android Notification通知使用詳解

    消息通知(Notification)是Android系統(tǒng)中比較有特色的一個功能,當(dāng)某個應(yīng)用程序希望用戶發(fā)出一些提示信息,而該應(yīng)用又不在前臺運行時,就可以借助通知來實現(xiàn)
    2022-09-09
  • Android 利用ViewPager+GridView實現(xiàn)首頁導(dǎo)航欄布局分頁效果

    Android 利用ViewPager+GridView實現(xiàn)首頁導(dǎo)航欄布局分頁效果

    用ViewPager+GridView實現(xiàn)首頁導(dǎo)航欄布局分頁效果來實現(xiàn)的效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-10-10
  • Android通過記住密碼功能學(xué)習(xí)數(shù)據(jù)存儲類SharedPreferences詳解及實例

    Android通過記住密碼功能學(xué)習(xí)數(shù)據(jù)存儲類SharedPreferences詳解及實例

    這篇文章主要通過“記住密碼”實例功能學(xué)習(xí)為大家介紹了Android數(shù)據(jù)存儲類SharedPreferences,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-03-03
  • MotionLayout自定義開關(guān)按鈕實例詳解

    MotionLayout自定義開關(guān)按鈕實例詳解

    這篇文章主要為大家介紹了MotionLayout自定義開關(guān)按鈕實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Android 簽名校驗與繞過思路詳解

    Android 簽名校驗與繞過思路詳解

    在 Android 應(yīng)用的安全體系中,簽名機(jī)制是保障 APK 完整性與可信來源的關(guān)鍵手段,本篇文章將從簽名校驗的原理出發(fā),介紹常見的繞過方式,并分析開發(fā)者與逆向工程師之間的“攻防博弈”,感興趣的朋友一起看看吧
    2025-06-06
  • Android 跨進(jìn)程模擬按鍵(KeyEvent )實例詳解

    Android 跨進(jìn)程模擬按鍵(KeyEvent )實例詳解

    這篇文章主要介紹了Android 跨進(jìn)程模擬按鍵(KeyEvent )實例詳解的相關(guān)資料,類似手機(jī)遙控器的需求就可以這么做,需要的朋友可以參考下
    2016-11-11
  • 淺談關(guān)于Android WebView上傳文件的解決方案

    淺談關(guān)于Android WebView上傳文件的解決方案

    這篇文章主要介紹了淺談關(guān)于Android WebView上傳文件的解決方案 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Android Service生命周期詳解

    Android Service生命周期詳解

    Android Service 生命周期可以促使移動設(shè)備的創(chuàng)新,讓用戶體驗到最優(yōu)越的移動服務(wù),只有broadcast receivers執(zhí)行此方法的時候才是激活的,當(dāng) onReceive()返回的時候,它就是非激活狀態(tài)
    2015-11-11

最新評論

道孚县| 栾川县| 长乐市| 万宁市| 蒲城县| 浪卡子县| 虞城县| 平远县| 阳谷县| 婺源县| 丰城市| 资中县| 邹城市| 新丰县| 通州市| 洛隆县| 抚松县| 沧源| 常德市| 二连浩特市| 于田县| 泰兴市| 阿城市| 新宁县| 岚皋县| 缙云县| 宁安市| 绿春县| 怀柔区| 四平市| 通城县| 南丹县| 石嘴山市| 岳阳市| 梓潼县| 福泉市| 文安县| 庆安县| 乐业县| 柳州市| 江津市|