LiveData那些事情,看我一篇就够了

一.LiveDataBus事件总线封装

参考文章

方案一:只支持粘性

object LiveDataBus {
    private val mBus = hashMapOf<String, SingleLiveData<Any>>()

    fun <T>with(channel: String): SingleLiveData<T> {
        if (!mBus.containsKey(channel)) {
            mBus[channel] = SingleLiveData()
        }
        return mBus[channel]!! as SingleLiveData<T>
    }
    class SingleLiveData<T> : MutableLiveData<T>() {
        val mPending= AtomicBoolean(false)
        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner) { t ->
                if (mPending.compareAndSet(true, false)) {
                    observer.onChanged(t)
                }
            }
        }

        override fun setValue(value: T?) {
            mPending.set(true)
            super.setValue(value)
        }

        fun clean(){
            setValue(null)
        }
    }
}

方案二:粘性和非粘性

object LiveDataBus2{
    private val bus: MutableMap<String, BusMutableLiveData<Any>> = mutableMapOf()

    fun <T> with(key: String): BusMutableLiveData<T> {
        if (!bus.containsKey(key)) {
            bus[key] = BusMutableLiveData()
        }
        return bus[key] as BusMutableLiveData<T>
    }

    class BusMutableLiveData<T> : MutableLiveData<T>() {
        private val observerMap: MutableMap<Observer<*>, Observer<*>> = mutableMapOf()

        fun observeSticky(
            owner: () -> Lifecycle,
            observer: (T) -> Unit
        ) {
            super.observe(owner, observer)
        }

        fun observeForeverSticky(observer: Observer<in T>) {
            super.observeForever(observer)
        }

        override fun observeForever(observer: Observer<in T>) {
            if (!observerMap.containsKey(observer)) {
                observerMap[observer] = ObserverWrapper(observer)
            }
            super.observeForever(observerMap[observer] as Observer<in T>)
        }

        override fun removeObserver(observer: Observer<in T>) {
            val realObserver: Observer<in T> =
                if (observerMap.containsKey(observer)) {
                    observerMap.remove(observer) as Observer<in T>
                } else {
                    observer
                }
            super.removeObserver(realObserver)
        }

        override fun observe(
            owner: LifecycleOwner,
            observer: Observer<in T>
        ) {
            super.observe(owner, observer)
            try {
                hook(observer)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        /**
         * 利用反射将 LiveData 的 mVersion 赋值给 ObserverWrapper 的 mLastVersion
         */
        @Throws(Exception::class)
        private fun hook(observer: Observer<*>) {
            // Get wrapper's version.
            val liveDataClass = LiveData::class.java
            // SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers
            val observersField = liveDataClass.getDeclaredField("mObservers")
            observersField.isAccessible = true
            val observers = observersField[this]
            val observersClass: Class<*> = observers.javaClass
            // It's mObservers's get method.
            val methodGet = observersClass.getDeclaredMethod("get", Any::class.java)
            methodGet.isAccessible = true
            val observerWrapperEntry = methodGet.invoke(observers, observer)
            var observerWrapper: Any? = null
            if (observerWrapperEntry is Map.Entry<*, *>) {
                // Now we got observerWrapper.
                observerWrapper = observerWrapperEntry.value
            }
            if (observerWrapper == null) {
                throw NullPointerException("Wrapper can not be null!")
            }
            val observerWrapperParentClass: Class<*>? = observerWrapper.javaClass.superclass
            val lastVersionField = observerWrapperParentClass!!.getDeclaredField("mLastVersion")
            lastVersionField.isAccessible = true
            // Get livedata's version.
            val versionField = liveDataClass.getDeclaredField("mVersion")
            versionField.isAccessible = true
            val version = versionField[this]
            // Set wrapper's version.
            lastVersionField[observerWrapper] = version
        }
    }

    private class ObserverWrapper<T>(val observer: Observer<T>) : Observer<T> {
        override fun onChanged(t: T) {
            if (isCallOnObserverForever()) {
                return
            }
            observer.onChanged(t)
        }

        private fun isCallOnObserverForever(): Boolean {
            val stackTrace = Thread.currentThread().stackTrace
            for (element in stackTrace) {
                if ("androidx.lifecycle.LiveData" == element.className
                    && "observeForever" == element.methodName
                ) {
                    return true
                }
            }
            return false
        }
    }


}

发送数据:

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //发送数据
        LiveDataBus2.with<String>("from_main")
            .value = "From MainActivity."
        //发送数据
        LiveDataBus.with<String>("from_main")
            .value = "From MainActivity111."
    }

    fun tiao(view: View) {
        val intent = Intent(this, MainActivity2::class.java)
        startActivity(intent)
    }
}

接受数据:

class MainActivity2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        LiveDataBus2.with<String>("from_main")
            .observe(this::getLifecycle) {
                Log.e("ytx", it)
            }
        LiveDataBus.with<String>("from_main")
            .observe(this::getLifecycle) {
                Log.e("ytx", it)
            }
    }
}

总结:方案2要比方案1功能更全。支持粘性和非粘性

二.LiveDataBus数据倒灌/粘性数据问题解决

参考文章
屏幕旋后转打印2次

class MainActivity3 : AppCompatActivity() {
    val networkData = MutableLiveData<String>()
    init {
        networkData.value = "hahaha" //
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main3)
        networkData.observe(this){
            Log.d("ytx", "数据: ")
        }

    }
}

三.第三方:UnPeekLiveData

github搜索

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例: 首先,我们需要在 `build.gradle` 文件中添加以下依赖项: ``` implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' ``` 然后,我们需要创建一个包含计分逻辑的 `ScoreViewModel` 类,该类将托管我们的数据。该类需要继承自 `ViewModel`。 ```kotlin import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class ScoreViewModel : ViewModel() { val teamAScore = MutableLiveData<Int>() val teamBScore = MutableLiveData<Int>() init { teamAScore.value = 0 teamBScore.value = 0 } fun addTeamAScore() { teamAScore.value = teamAScore.value?.plus(1) } fun addTeamBScore() { teamBScore.value = teamBScore.value?.plus(1) } } ``` 上述代码中,我们创建了一个 `ScoreViewModel` 类,该类包含两个 `MutableLiveData`,即 `teamAScore` 和 `teamBScore`。这两个变量存储着两个球队的得分,并且在我们的应用程序中可以随时更新。 我们还包含了两个方法 `addTeamAScore()` 和 `addTeamBScore()`,分别用于增加对应球队的得分。 接下来,我们需要创建一个 `MainActivity` 类,该类将托管我们的用户界面。 ```kotlin import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private lateinit var scoreViewModel: ScoreViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) scoreViewModel = ViewModelProviders.of(this).get(ScoreViewModel::class.java) scoreViewModel.teamAScore.observe(this, Observer { score -> team_a_score.text = score.toString() }) scoreViewModel.teamBScore.observe(this, Observer { score -> team_b_score.text = score.toString() }) team_a_plus.setOnClickListener { scoreViewModel.addTeamAScore() } team_b_plus.setOnClickListener { scoreViewModel.addTeamBScore() } } } ``` 上述代码中,我们创建了一个 `MainActivity` 类,并在其中创建了一个 `ScoreViewModel` 的实例。 我们还使用了 `ViewModelProviders.of()` 方法来获取 `ScoreViewModel` 的实例,并使用 `observe()` 方法来观察 `teamAScore` 和 `teamBScore` 变量。每当这些变量更新时,我们将更新 UI 中对应的文本视图。 最后,我们为两个加分按钮设置了点击侦听器,并使用 `addTeamAScore()` 和 `addTeamBScore()` 方法来增加对应球队的得分。 现在,当您运行应用程序时,您将看到两个球队的得分,并且您可以使用加分按钮来增加它们的分数。同时,这些更改将保存在 `ScoreViewModel` 中,并在配置更改后保持不变。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值