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

目录

  • 一、LiveData的基本使用
    • 1. 使用方式一
    • 2. 使用方式二
    • 3. 使用方式三
  • 二、LiveData 去除黏性数据的方法
    • 1. 去除黏性的Java版本
    • 2. 去除黏性的Kotlin版本

一、LiveData的基本使用

1. 使用方式一

MyLiveData.kt

package com.example.mylivedata.simple1

import androidx.lifecycle.MutableLiveData

object MyLiveData {  // 单例

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

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 { t ->
            textView.text = t // 更新UI
        })

        // 完整写法  new Observer 重写onChange方法
        MyLiveData.info.observe(this, object : Observer {
            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 by lazy { MutableLiveData()}

    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

3. 使用方式三

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

package com.example.mylivedata.simple3

import androidx.lifecycle.MutableLiveData

object MyLiveData {

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

}

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

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 {
            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> bus;
    private static OkLiveDataBusJava liveDataBus = new OkLiveDataBusJava();

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

    public static OkLiveDataBusJava getInstance() {
        return liveDataBus;
    }

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

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

        private void hook(Observer observer) {
            try {
                // TODO 1.得到mLastVersion
                // 获取到LiveData类中的mObservers对象
                Class liveDataClass = LiveData.class;
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
                // 获取到这个成员变量的对象
                Object mObserversObject = mObserversField.get(this);
                // 得到map对象的class对象   private SafeIterableMap, 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> by lazy { HashMap>() }

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

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

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

        override fun observe(owner: LifecycleOwner, observer: Observer) {
            super.observe(owner, observer)

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

        private fun hook(observer: Observer) {
            // 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, ObserverWrapper> mObservers = new SafeIterableMap<>();
            val mObserversClass : Class<*> = mObserversObject.javaClass

            // 获取到mObservers对象的get方法, protected Entry 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

MainActivity2.kt

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")
        }

    }
}

你可能感兴趣的:(Android,kotlin,LiveData)