阅读 225

LiveData初识

LiveData使用

1.在Activity 中 通过 ViewModelProvider(this).get(XxxViewModel::class.java) 获取到XxxViewModel对象

2.通过XxxViewModel对象获取到定义在XxxViewModel中的liveData

3.通过liveData的observe方法 监测数据发生改变回调弹出吐丝

4.通过按钮点击事件模拟数据发生改变

代码如下:

//Activity中代码
  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        observeLiveData()
    }

   fun onClick(v: View) {
        when (v.id) {
            //通过按钮点击事件模拟数据发生改变 
            R.id.btn_00 -> {
               var  viewModel =  ViewModelProvider(this).get(MusicViewModel::class.java)
                viewModel.changeItem(0,"009")
            }
        }
    }

 fun observeLiveData(){
       var  viewModel =  ViewModelProvider(this).get(MusicViewModel::class.java)
        viewModel.musics.observe(this,  Observer<List<String>>() { str ->
            //数据发生改变 弹出吐司
            Toast.makeText(this, str.toString(), Toast.LENGTH_SHORT).show()
        })
    }
复制代码
public class MusicViewModel extends ViewModel {

    // 定义一个对象,相当于用来存放数据的仓库
    private static MutableLiveData<List<String>> liveData;

    /**
     * 用于获取数据
     * 并保存到LiveData中(可以理解成数据仓库)
     */
    public MutableLiveData<List<String>> getMusics() {
        if (liveData == null) {
            List<String> musics = loadMusics();
            liveData = new MutableLiveData<>();
            //liveData.setValue(musics);
            // 把数据存放到仓库
            // post 和 set 是跟同步异步区别
            liveData.postValue(musics);
        }
        return liveData;
    }

    /**
     * 加载数据
     * 可以从本地或者通过服务端请求获得
     */
    private List<String> loadMusics() {
        List<String> musics = new ArrayList<>();
        musics.add("001");
        musics.add("002");
        musics.add("003");
        return musics;
    }

    /**
     * 修改某条数据
     */
    public void changeItem(int index, String music) {
        List<String> musics = liveData.getValue();
        musics.set(index, music);
        liveData.postValue(musics);
    }
}

复制代码
LiveData简单封装成LiveDataBus实现EventBus发布订阅式效果:

LiveDataBus

public class LiveDataBus {

    private static LiveDataBus instance;

    private Map<String, MutableLiveData> bus;

    public static LiveDataBus getInstance() {
        if (instance == null) {
            synchronized (LiveDataBus.class) {
                if (instance == null) {
                    instance = new LiveDataBus();
                }
            }
        }
        return instance;
    }

    private LiveDataBus() {
        bus = new ConcurrentHashMap<>();
    }

    public synchronized <T> MutableLiveData<T> with(String key, Class<T> type) {
        if (!bus.containsKey(key)) {
            bus.put(key, new MutableLiveData<>());
        }
        // 如果不需要阻止黏性事件,则换回MutableLiveData
        return (MutableLiveData<T>) bus.get(key);
    }

}
复制代码

在Activity中使用LiveDataBus:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        registerLiveDataBus()
    }
    
    fun registerLiveDataBus(){

        //这里我们注册一个test01事件 参数类型是String
        LiveDataBus.getInstance().with("test01",String::class.java)
            .observe(this, Observer<String>() {str->
                Toast.makeText(this, str, Toast.LENGTH_SHORT).show()
            })

    }
    
    fun onClick(v: View) {

        when (v.id) {

            //发送事件 上面registerLiveDataBus方法中就会弹出吐司
            R.id.btn_00 -> {
                LiveDataBus.getInstance().with("test01",String::class.java)
                    .postValue("001")
            }
        }
    }

复制代码
解决LiveDataBus黏性事件bug

继承LiveData类替换系统的MutableLiveData 代码如下:

public class MLiveData<T> extends LiveData<T> {

    private boolean hasModified = false;

    private Handler handler;

    // 只有onStart后,对数据的修改才会触发 observer.onChanged()
    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
        super.observe(owner, new Observer<T>() {
            private boolean hasIntercept = false;

            // 创建了一个新的Observer来包装处理我们传入的observer
            @Override
            public void onChanged(T t) {

                // 通过逻辑判断来解决不需要粘性事件的情况
                if (!hasModified || hasIntercept) {
                    observer.onChanged(t);
                }
                hasIntercept = true;
            }
        });
    }

    // 无论何时,只要数据发生改变,就会触发 observer.onChanged()
    @Override
    public void observeForever(@NonNull final Observer<? super T> observer) {
        super.observeForever(new Observer<T>() {
            private boolean hasIntercept = false;

            @Override
            public void onChanged(T t) {
                if (!hasModified || hasIntercept) {
                    observer.onChanged(t);
                }
                hasIntercept = true;
            }
        });
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
        hasModified = true;
        LogUtil.e("MLiveData hasModified=" + hasModified);
    }

    /**
     * 这里可能存在问题?
     * 第一次需要使用handler来解决hasModified在异步情况先先改变的问题
     *
     * @param value
     */
    @Override
    public void postValue(T value) {
        super.postValue(value);
        if (handler == null) {
            handler = new Handler(Looper.getMainLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    hasModified = true;
                }
            });
        } else {
            hasModified = true;
        }
        // 不能直接修改hasModified值,因为异步情况导致还没onChanged调用就到这里了
        // hasModified = true;
    }

}
复制代码
文章分类
Android
文章标签