LiveData相关基本使用及去除黏性数据的方法

这篇具有很好参考价值的文章主要介绍了LiveData相关基本使用及去除黏性数据的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、LiveData的基本使用

  LiveData添加一个观察者时,会关联一个LifecycleOwner,然后把这个观察者(observer)与 owner包装成一个LifecycleBoundObserver,和LifecycleOwner的getLifecycle关联,当LifecycleBoundObserver的生命周期变化时,会调用LifecycleBoundObserver的onStateChange()方法,在这个方法中判断当前生命周期和上次的生命周期是否是同一类型(要么活跃,要么非活跃),如果是就之间返回,避免重复通知(start通知了,resume就不再需要通知了),如果不是同一类型,并且当前生命周期是活跃状态,就调用dispatchingValue()方法通知观察者,判断LifecycleOwner是否活跃状态,如果是,将LiveData中持有的最新数据更新给观察者。

1. 使用方式一

MyLiveData.kt

package com.example.mylivedata.simple1

import androidx.lifecycle.MutableLiveData

object MyLiveData {  // 单例

    // 懒加载
    val info : MutableLiveData<String> by lazy { MutableLiveData<String>() }
}

MainActivity.kt

package com.example.mylivedata.simple1

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.lifecycle.Observer
import com.example.mylivedata.R
import kotlin.concurrent.thread

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView : TextView = findViewById(R.id.tv_textView)

        // TODO 1.观察者 环节
        MyLiveData.info.observe(this, Observer<String> { t ->
            textView.text = t // 更新UI
        })

        // 完整写法  new Observer 重写onChange方法
        MyLiveData.info.observe(this, object : Observer<String> {
            override fun onChanged(t: String?) {
                textView.text = t  // 更新UI
            }

        })

        // TODO 2.触发数据改变  环节
        MyLiveData.info.value = "default"  // setValue  主线程

        thread {
            Thread.sleep(3000)
            MyLiveData.info.postValue("三秒钟后,修改了哦")  // postValue 子线程
        }

        thread {
            Thread.sleep(6000)
            MyLiveData.info.postValue("六秒钟后,修改了哦")  // postValue 子线程
        }

    }
}

2. 使用方式二

MyLiveData.kt

package com.example.mylivedata.simple2

import androidx.lifecycle.MutableLiveData

object MyLiveData {  // 单例

    // 这里为data的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
    val data : MutableLiveData<String> by lazy { MutableLiveData<String>()}

    init {
        // data.value = "dafault" // 违背 在子线程setValue(SetValue在主线程中执行)
        data.postValue("test")  // 子线程 执行postValue(postValue在子线程中执行)
    }

}

MyServer.kt

package com.example.mylivedata.simple2

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log
import kotlin.concurrent.thread

// 模拟后台推送
class MyServer : Service() {
    override fun onBind(intent: Intent?): IBinder? = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        thread {
            for ( x in 1 .. 1000) {
                Log.d("MyServer", "服务器给你推送消息(叮咚声响),消息内容是:${x}")
                MyLiveData.data.postValue("服务器给你推送消息啦,消息内容是:${x}")
                Thread.sleep(2000)  // 2秒推送一次
            }
        }
        return super.onStartCommand(intent, flags, startId)
    }
}

MainActivity2.kt

package com.example.mylivedata.simple2

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.mylivedata.R
import java.util.*

class MainActivity2 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        // 启动服务
        val button = findViewById<Button>(R.id.bt)
        button.setOnClickListener {
            startService(Intent(this, MyServer::class.java))
            Toast.makeText(this, "推送服务器启动成功", Toast.LENGTH_SHORT).show()
        }

        // 观察者 界面可见的情况下,才能做事情
        MyLiveData.data.observe(this, androidx.lifecycle.Observer {
            Log.d("MyServer", "界面可见,说明用户在查看列表界面啦,更新信息列表UI界面:${it}")
            Toast.makeText(this, "更新消息列表UI界面成功:${it}", Toast.LENGTH_SHORT).show()
        })

    }
}

3. 使用方式三

该方式使用的是黏性数据
MyLiveData.kt

package com.example.mylivedata.simple3

import androidx.lifecycle.MutableLiveData

object MyLiveData {

    // 这里的data的MutableLiveData 懒加载初始化(懒加载:用到时才加载)
    val data : MutableLiveData<String> by lazy { MutableLiveData<String>() }

}

MainActivity3.kt

package com.example.mylivedata.simple3

import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.example.mylivedata.R

class MainActivity3 : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main3)

        val button = findViewById<Button>(R.id.button)
        button.setOnClickListener {
            MyLiveData.data.value = "我就是我,不一样的烟火"

            startActivity(Intent(this, MainActivity4::class.java))
        }
    }
}

MainActivity4.kt

package com.example.mylivedata.simple3

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import com.example.mylivedata.R

class MainActivity4 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main4)

        // 后观察数据,居然能够收到 前面修改的数据,这就是 数据黏性
       /*
       MyLiveData.data.observe(this, Observer {
            Toast.makeText(this, "观察者数据变化:${it}", Toast.LENGTH_SHORT).show()
        })
        */
        MyLiveData.data.observe(this, object : Observer<String> {
            override fun onChanged(t: String?) {
                Toast.makeText(this@MainActivity4, "观察者数据变化:$t", Toast.LENGTH_SHORT).show()
            }

        })

        // 此观察者 和handler没有区别,一股脑的执行(极端的情况,可以用)
        // 但是需要手动考虑释放工作
        //MyLiveData.data.observeForever {  }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 手动释放
        //MyLiveData.data.removeObserver()
    }
}

二、LiveData 去除黏性数据的方法

1. 去除黏性的Java版本

OkLiveDataBusJava.java

package com.example.mylivedata.simple4;

import androidx.annotation.NonNull;
import androidx.arch.core.internal.SafeIterableMap;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 单例模式 去掉粘性事件  Java版本
 */
public class OkLiveDataBusJava {

    // 存放订阅者
    private Map<String, BusMutableLiveData<Object>> bus;
    private static OkLiveDataBusJava liveDataBus = new OkLiveDataBusJava();

    private OkLiveDataBusJava() {
        bus = new HashMap<>();
    }

    public static OkLiveDataBusJava getInstance() {
        return liveDataBus;
    }

    // 注册订阅者
    public synchronized <T> BusMutableLiveData<T> with(String key, Class<T> type) {
        if (bus.containsKey(key)) {
            bus.put(key, new BusMutableLiveData<>());
        }
        return (BusMutableLiveData<T>) bus.get(key);
    }

    public static class BusMutableLiveData<T> extends MutableLiveData<T> {
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            super.observe(owner, observer);  // 启用系统的功能,不写就破坏了
            hook(observer);
        }

        private void hook(Observer<? super T> observer) {
            try {
                // TODO 1.得到mLastVersion
                // 获取到LiveData类中的mObservers对象
                Class<LiveData> liveDataClass = LiveData.class;
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
                // 获取到这个成员变量的对象
                Object mObserversObject = mObserversField.get(this);
                // 得到map对象的class对象   private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
                Class<?> mObserversClass = mObserversObject.getClass();
                // 获取到mObservers对象的get方法
                Method get = mObserversClass.getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
                // 执行get方法
                Object invokeEntry = get.invoke(mObserversObject, observer);
                // 取到entry中的value
                Object observerWrapper = null;
                if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
                    observerWrapper = ((Map.Entry) invokeEntry).getValue();
                }
                if (observerWrapper == null) {
                    throw new NullPointerException("observerWrapper is null");
                }

                // 得到observerWrapper的类对象
                // observerWrapper.getClass() 获取的是LifecycleBoundObserver类对象
                // observerWrapper类是LifecycleBoundObserver类的父类
                Class<?> supperClass = observerWrapper.getClass().getSuperclass();
                Field mLastVersion = supperClass.getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);

                // TODO 2.得到mVersion
                Field mVersion = liveDataClass.getDeclaredField("mVersion");
                mVersion.setAccessible(true);

                // TODO 3.mLastVersion = mVersion
                Object mVersionValue = mVersion.get(this);
                mLastVersion.set(observerWrapper, mVersionValue);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2. 去除黏性的Kotlin版本

OKLiveDataBusKT.kt

package com.example.mylivedata.simple4

import android.util.Log
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.lang.NullPointerException
import java.lang.reflect.Field
import java.lang.reflect.Method

/**
 * 单例模式 去掉黏性事件(有关闭黏性的开关)KT版本
 */
object OKLiveDataBusKT {

    // 存放订阅者
    private val bus : MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap<String, BusMutableLiveData<Any>>() }

    // 暴露一个函数,给外界注册,订阅者关系
    fun <T> with(key : String, type : Class<T>, isStack : Boolean = true) : BusMutableLiveData<T> {
        if (!bus.containsKey(key)) {
            bus[key] = BusMutableLiveData(isStack)
        }
        return bus[key] as BusMutableLiveData<T>
    }

    class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {
        var isStack : Boolean = false

        // 次构造
        constructor(isStack: Boolean) : this() {
            this.isStack = isStack
        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)

            if (!isStack) {
                hook(observer)
                Log.d("abc", "Kotlin版本 不启用黏性")
            } else {
                Log.d("abc", "Kotlin版本 启用黏性")
            }
        }

        private fun hook(observer: Observer<in T>) {
            // TODO 1.得到mLastVersion
            // 获取到LiveData的类中的mObservers对象
            val liveDataClass = LiveData::class.java
            val mObserversField = liveDataClass.getDeclaredField("mObservers")
            mObserversField.isAccessible = true  // 私有修饰可以访问

            // 获取到这个成员变量的对象 Kotlin Any == Java Object
            val mObserversObject : Any = mObserversField.get(this)

            // 得到map对象的class对象  private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
            val mObserversClass : Class<*> = mObserversObject.javaClass

            // 获取到mObservers对象的get方法, protected Entry<K, V> get(K k)
            val get : Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
            get.isAccessible = true  // 私有修饰也可以访问

            // 执行get方法
            val invokeEntry : Any = get.invoke(mObserversObject, observer)

            // 取到entry中的value
            var observerWrapper : Any? = null
            if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
                observerWrapper = invokeEntry.value
            }
            if (observerWrapper == null) {
                throw NullPointerException("observerWrapper is null")
            }

            // 得到observerWrapper的类对象
            val supperClass : Class<*> = observerWrapper.javaClass.superclass
            val mLastVersion : Field = supperClass.getDeclaredField("mLastVersion")
            mLastVersion.isAccessible = true

            // TODO 2.得到mVersion
            val mVersion : Field = liveDataClass.getDeclaredField("mVersion")
            mVersion.isAccessible = true

            // TODO 3.mLastVersion = mVersion
            val mVersionValue = mVersion.get(this)
            mLastVersion.set(observerWrapper, mVersionValue)
         }
    }
}

MainActivity.kt

package com.example.mylivedata.simple4

import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.example.mylivedata.R

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // LiveData发生消息通知所有的观察者数据变化了
        // KT版本 旧数据  黏性数据
        OKLiveDataBusKT.with("data1", String::class.java).value = "liveData  kotlin数据"
        // Java版本
        OkLiveDataBusJava.getInstance().with("data2", String::class.java).value = "livaData java数据"

        // 点击事件,跳转到下一个Activity
        val button = findViewById<Button>(R.id.button)
        button.setOnClickListener {
            startActivity(Intent(this, MainActivity2::class.java))
        }
    }
}

MainActivity2.kt文章来源地址https://www.toymoban.com/news/detail-671416.html

package com.example.mylivedata.simple4

import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import com.example.mylivedata.R
import kotlin.concurrent.thread

class MainActivity2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        // Kotlin版本订阅观察者
        OKLiveDataBusKT.with("data1", String::class.java).observe(this, Observer(){
            Toast.makeText(this, "Kotlin版本的观察者:${it}", Toast.LENGTH_SHORT).show()
            Log.d("abc", "Kotlin版本的观察者:${it}")

        })

        // Java版本订阅观察者(Java是模拟剔除黏性的)
        OkLiveDataBusJava.getInstance().with("data2", String::class.java).observe(this, Observer() {
            Toast.makeText(this, "Java版本的观察者:${it}", Toast.LENGTH_SHORT).show()
            Log.d("abc", "Java版本的观察者:${it}")
        })

        thread {
            Thread.sleep(2000)
            OKLiveDataBusKT.with("data1", String::class.java).postValue("2222")
        }

        thread {
            Thread.sleep(4000)
            OkLiveDataBusJava.getInstance().with("data2", String::class.java).postValue("4444")
        }

    }
}

到了这里,关于LiveData相关基本使用及去除黏性数据的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Architecture Components ——LiveData使用,android热修复视频

    小结:getApplication()即是全局的上下文 Activity中进行数据监听 import android.arch.lifecycle.MutableLiveData; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log;

    2024年04月17日
    浏览(45)
  • Android-Jetpack>;>; LiveData粘性数据

    米哈游校招技术提前批来啦 靠谱内推,全程跟进! 有需要的小伙伴可以帮忙辅导简历哈! 投递后可私信我跟进~ 内推码:NE449    入职 南大通用 个人感受 Hello啊各位朋友们,这里先说一下个人情况吧,我是河北工业大学23届的本科生,计算机本专业的。然后我是春招进的南

    2024年02月17日
    浏览(62)
  • Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(三)

    之前几篇文章,我们通过一个简单的实例需求,将LiveData引入了进来,从而知道了使用它的好处。然后我们通过对其原理的猜想,实现方案的步步探索,自己通过编码实现了LiveData框架。 Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(一) Android Jetpack 从使用到源码

    2024年02月04日
    浏览(42)
  • Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(二)

    上文,我们就一个实例需求,引入了LiveData进行了实现,大家通过前后的编码实现方案对比,可以感受到LiveData的好用。不由的为jetpack组件的开发者点赞。 Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(一) Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】

    2024年02月08日
    浏览(36)
  • Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(四)

    前面,经过LiveData的使用、自我编程实现LiveData框架、Jetpack LiveData源码探索几节的学习,相信大家都收益匪浅。 Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(一) Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(二) Android Jetpack 从使用到源码深耕【Li

    2024年02月04日
    浏览(42)
  • PyTorch 之 简介、相关软件框架、基本使用方法、tensor 的几种形状和 autograd 机制

    本文参加新星计划人工智能(Pytorch)赛道:https://bbs.csdn.net/topics/613989052 PyTorch 是一个基于 Torch 的 Python 开源机器学习库,用于自然语言处理等应用程序。它主要由 Facebook 的人工智能小组开发,不仅能够实现强大的 GPU 加速,同时还支持动态神经网络,这一点是现在很多主流框架

    2024年01月18日
    浏览(54)
  • Android架构组件LiveData

    LiveData LiveData是基于观察者模式创建的,其中,LiveData是被观察者,观察者通过注册方法,监听被观察者的数据变化。LiveData在数据发生变化的时候,会通知观察者。 LiveData是一个容器,存放数据的容器,它的数据变化可以被监听,也就是LiveData是一个被观察者,如下,创建了一

    2024年02月13日
    浏览(36)
  • Android JetPack深入分析LiveData源码

    Google Android开发者 LiveData概览 在了解 LiveData 源码之前,建议先了解 LifeCycle 相关知识,请参考:Android JetPack深入分析Lifecycle源码 定义 从定义中,我们可以大概知道: LiveData 是一个数据存储类,能够感知 Activity 、 Fragment 等组件的生命周期,并且支持对它存储的数据进行观察

    2024年02月12日
    浏览(45)
  • Android资深工程书之LiveData核心组件原理剖析

    LiveData是Android架构组件库中的一个类,用于在应用程序组件之间共享数据。它是一种可观察的数据持有者,可以感知应用程序组件的生命周期,并在数据发生变化时通知观察者。 在Android应用程序中使用LiveData,你可以按照以下步骤进行: 创建LiveData实例: 在ViewModel类中创建

    2024年02月12日
    浏览(40)
  • Android使用SQLite数据库实现基本的增删改查

    目录 一、创建activity_main和MainActivity界面 二、实现查询/删除功能创建activity_delete和DeleteActivity 三、实现添加功能创建activity_add和AddActivity  四、实现更新功能创建activity_update和UpdateActivity 五、创建user_data类、userInfo类和增加权限 总结 activity_main如图:  MainActivity如下 layout界面

    2024年02月08日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包