Android livedata原理解析之自己实现一个简单的LiveData
LiveData其实就是通过管理生命周期来实现当视图不可见时不渲染数据,当视图可见时再渲染数据.当在一个Activity发送一个网络请求后,立马切到另一个界面或都按下Home键,使得视图不可见..这个时候网络请求还在进行,当网络请求完成后,会判断这个界面是活跃状态还是不活跃状态,如果是不活跃状态则把数据保存在一个缓存集合里面,当这个视图可见时,就会回调其onStart方法,这里我们就可以监听到,然后将缓存数据显示到界面..
那么自己也写一个
创建一个生命周期接口
public interface Lifecycle {void onCreate(int activityCode);void onStart(int activityCode);void onStop(int activityCode);void onPause(int activityCode);void onDetach(int activityCode);
}
创建一个自己的LiveData类并实现Lifecycle
public class LiveData<T> implements Lifecycle {
}
监听事件,我们肯定需要一个观察者,创建一个
public abstract class Observer<T> {//活跃状态 可能收到消息static final int STATE_ACTIVE = 1;//暂停状态,不能收到消息static final int STATE_ONPAUSE = 2;//销毁状态static final int STATE_ONDESTORY = 3;//初始化状态static final int STATE_ONINIT = 0;private int state = STATE_ONINIT;public int getState() {return state;}public void setState(int state) {this.state = state;}public abstract void onChanged(T t);}
我们LiveData肯定要管理所有注册的观察者,所以里面肯定有个管理集合,还要提供一个注册的方法
// Integer是我们Activity的hashcode值
private Map<Integer, Observer<T>> observers = new HashMap<>();//进行注册
public void observe(FragmentActivity activity, Observer<T> observer) {observers.put(activity.hashCode(), observer);
}
最后就是要设置值来达到显示数据的作用
public void setValue(T value) {for (Map.Entry<Integer, Observer<T>> entry : observers.entrySet()) {Observer<T> observer = entry.getValue();Integer activityCode = entry.getKey();observer.onChanged(value);}
这样所有注册了的观察都就都能收到数据.
现在来完成怎样管理生命周期
一般管理生命周期都是一个道理,用一个没有界面的fragment来完成,我们这也一样创建一个LifeFragment
public class LifeFragment extends Fragment {private Lifecycle mLifecycle;private int activityCode;public void setLifecycle(Lifecycle lifecycle){this.mLifecycle = lifecycle;}@Overridepublic void onAttach(Activity activity) {super.onAttach(activity);activityCode = activity.hashCode();if (mLifecycle != null) {mLifecycle.onCreate(activityCode);}}@Overridepublic void onDetach() {super.onDetach();if (mLifecycle != null) {mLifecycle.onDetach(activityCode);}}@Overridepublic void onPause() {super.onPause();if (mLifecycle != null) {mLifecycle.onPause(activityCode);}}@Overridepublic void onStop() {super.onStop();if (mLifecycle != null) {mLifecycle.onStop(activityCode);}}@Overridepublic void onStart() {super.onStart();if (mLifecycle != null) {mLifecycle.onStart(activityCode);}}
}
然后回来我们LiveData类里面的注册方法里面,应该添加创建LifeFragment方法并设置监听
public void observe(FragmentActivity activity, Observer<T> observer) {FragmentManager fm = activity.getSupportFragmentManager();observers.put(activity.hashCode(), observer);LifeFragment fragment = (LifeFragment) fm.findFragmentByTag("luckly.ancely.com.commonentmodule");if (fragment == null) {fragment = new LifeFragment();fm.beginTransaction().add(fragment, "luckly.ancely.com.commonentmodule").commitAllowingStateLoss();}fragment.setLifecycle(this);
}
这样我们就可以管理我们Actiity的生命周期了.这样就可以在不同的生命周期里面设置数据状态,如下
@Overridepublic void onCreate(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ONINIT);}@Overridepublic void onStart(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ACTIVE);}@Overridepublic void onStop(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ONPAUSE);}@Overridepublic void onPause(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ONPAUSE);}@Overridepublic void onDetach(int activityCode) {observers.remove(activityCode);}
然后在setValue方法里也要对不同的状态进行不一样的判断 完整代码如下
public void setValue(T value) {List<Observer> destory = new ArrayList<>();for (Map.Entry<Integer, Observer<T>> entry : observers.entrySet()) {Observer<T> observer = entry.getValue();Integer activityCode = entry.getKey();if (observer.getState() == Observer.STATE_ACTIVE) {//如果是活跃状态,直接设置observer.onChanged(value);}//如果是不活跃状态,则把数据添加到缓存集合里if (observer.getState() == Observer.STATE_ONPAUSE) {if (cacheValue.get(activityCode) == null) {cacheValue.put(activityCode,new ArrayList<T>());}if (!cacheValue.get(activityCode).contains(value)) {cacheValue.get(activityCode).add(value);}}//如果界面已经销毁了,则把其添加到销毁集合里,因为这是在遍历map集合,如果不能直接删除if (observer.getState() == Observer.STATE_ONDESTORY) {destory.add(observer);}}for (Observer observer : destory) {//最后把destory数据消除observers.remove(observer);}}
最后在我们的onStart回调里面设置数据
@Overridepublic void onStart(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ACTIVE);if (cacheValue.get(activityCode) == null||cacheValue.get(activityCode).size()==0) {return;}for (T t : cacheValue.get(activityCode)) {observers.get(activityCode).onChanged(t);}cacheValue.clear();}
这样我们自己的LiveData就全部实现了.贴一个LiveData全部代码
package luckly.ancely.com.commoentmodule.event;import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class LiveData<T> implements Lifecycle {//Integer activity地址private Map<Integer, Observer<T>> observers = new HashMap<>();private Map<Integer, List<T>> cacheValue = new HashMap<>();public void observe(FragmentActivity activity, Observer<T> observer) {FragmentManager fm = activity.getSupportFragmentManager();observers.put(activity.hashCode(), observer);LifeFragment fragment = (LifeFragment) fm.findFragmentByTag("luckly.ancely.com.commonentmodule");if (fragment == null) {fragment = new LifeFragment();fm.beginTransaction().add(fragment, "luckly.ancely.com.commonentmodule").commitAllowingStateLoss();}fragment.setLifecycle(this);}public void setValue(T value) {List<Observer> destory = new ArrayList<>();for (Map.Entry<Integer, Observer<T>> entry : observers.entrySet()) {Observer<T> observer = entry.getValue();Integer activityCode = entry.getKey();if (observer.getState() == Observer.STATE_ACTIVE) {observer.onChanged(value);}if (observer.getState() == Observer.STATE_ONPAUSE) {if (cacheValue.get(activityCode) == null) {cacheValue.put(activityCode,new ArrayList<T>());}if (!cacheValue.get(activityCode).contains(value)) {cacheValue.get(activityCode).add(value);}}if (observer.getState() == Observer.STATE_ONDESTORY) {destory.add(observer);}}for (Observer observer : destory) {observers.remove(observer);}}@Overridepublic void onCreate(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ONINIT);}@Overridepublic void onStart(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ACTIVE);if (cacheValue.get(activityCode) == null||cacheValue.get(activityCode).size()==0) {return;}for (T t : cacheValue.get(activityCode)) {observers.get(activityCode).onChanged(t);}cacheValue.clear();}@Overridepublic void onStop(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ONPAUSE);}@Overridepublic void onPause(int activityCode) {observers.get(activityCode).setState(Observer.STATE_ONPAUSE);}@Overridepublic void onDetach(int activityCode) {observers.remove(activityCode);cacheValue.clear();}
}
Android livedata原理解析之自己实现一个简单的LiveData相关推荐
- 爱加密Android APk 原理解析
转载请标明出处:http://blog.csdn.net/u011546655/article/details/45921025 爱加密Android APK加壳原理解析 一.什么是加壳? 加壳是在二 ...
- LiveData原理解析
什么是LiveData LiveData是Android Architecture Components 其中的一个组件.主要用于更新UI数据和组件之间传值. 1.LiveData是一种持有可被观察数 ...
- 深入了解Vue 2响应式原理,并手写一个简单的Vue
1. Vue 2的响应式原理 Vue.js 一个核心思想是数据驱动.所谓数据驱动是指视图是由数据驱动生成的,对视图的修改,不会直接操作 DOM,而是通过修改数据.vue.js里面只需要改变数据,Vue ...
- Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)
本文内容: 1.横向ListView的所有实现思路; 2.其中一个最通用的思路HorizontalListView,并基于横向ListView开发一个简单的相册: 3.实现的横向ListView在点击 ...
- Android—Gson原理解析
JsonElement 抽象类 代表json串的某一个元素 某一个元素: JsonObject JsonArray JsonPrimitive(基本类型) JsonNull JsonElement的四 ...
- android asynctask,Android AsyncTask原理解析
想要启动一个AsyncTask,首先需要创建一个AsyncTask对象然后调用execute方法.例如: new DownloadFilesTask().execute(); DownloadFile ...
- [Android开发] Json解析工具类,一个类搞定Json的解析
一.简介 利用递归的方式反射解析到bean里面 二.详细代码 1. Json格式 例如服务器指定规定json格式为: {"code": "--" , // 返回 ...
- BAT大量裁人,快35岁的程序员该何去何从,Android并发原理解析
行业前景 首先我给大家分析一下,现在行业的一个情况. 2018年IT界规模最大的裁员事件了.近日,面对难看的财务报表,美国最大的通讯运营商.市值2200亿美金的Verizon,遣散了4.4万名老员工. ...
- Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新
登陆时splash初始页调用接口检查app版本.如有更新,使用okGo的文件下载,保存到指定位置,调用Android安装apk. <!-- Android 8.0 (Android O)为了针对 ...
最新文章
- mysql链接数据库properties_mysql 之通过配置文件链接数据库
- 旅游O2O“三国杀”竞技:携程系「守」、飞猪「望」、美团「攻」
- PHP网站使用JavaScript和Iframe简单实现部分刷新效果
- 利用ipsec配置tcp/ip用于安全连接
- 《经济学人》新一期封面主题:Govcoins 改变金融的数字货币
- 使用jfreechart在jsp页面柱状图统计
- keras中的EarlyStopping
- wordpress后台加载速度异常缓慢排查记录(原创)
- 设计思想之高内聚低耦合
- 【无人机控制】四旋翼飞行器飞行控制系统含Matlab源码
- ansys时间步长怎么设置_ANSYS瞬态动力学分析中的时间步长的选择
- 长截图或长图片如何按页面切分后打印或插入到Word文档中
- 色彩三原色,RGB,CMYK
- P3840蜗牛一期--虚拟局域网VLAN
- math_数集(数集符号)/算数运算中英文对照
- 提供 Android 酷炫的开屏动画 (awesome-opening-animation)
- 【阅读笔记】Mutual CRF-GNN for Few-shot Learning
- linux系统etc什么意思,请问linux下的etc是什么意思?
- ChatGPT微信小程序搭建总结
- Hive任务执行报错:FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
热门文章
- JointJS实现节点自动布局
- Scrapy从入门到精通(3)--使用Item封装数据
- 【paper笔记】ESAM: Discriminative Domain Adaptation with Non-Displayed Items to Improve Long-Tail
- MTA网络基础考试准备指南
- ION内存管理器介绍
- GAMIT 分步进行基线解算流程
- Vue中的 key 的作用是什么?
- markdown编辑器自学+使用说明
- pyqt5 同时显示多个画面_体育赛事直播应用NHL.TV可让屏幕同时显示6个画面,全景观看比赛...
- 探秘李逵-全球顶级电竞俱乐部