当前位置: 首页 > wzjs >正文

12306网站开发费用网页是怎么制作的

12306网站开发费用,网页是怎么制作的,网站手机开,江苏省建设工程备案网站LiveData 工作原理 数据持有与观察者管理:LiveData 内部维护着一个数据对象和一个观察者列表。当调用 observe 方法注册观察者时,会将 LifecycleOwner 和 Observer 包装成 LifecycleBoundObserver 对象并添加到观察者列表中。生命周期感知:L…

LiveData 工作原理

  • 数据持有与观察者管理LiveData 内部维护着一个数据对象和一个观察者列表。当调用 observe 方法注册观察者时,会将 LifecycleOwner 和 Observer 包装成 LifecycleBoundObserver 对象并添加到观察者列表中。
  • 生命周期感知LifecycleBoundObserver 实现了 LifecycleEventObserver 接口,能够监听 LifecycleOwner 的生命周期变化。当 LifecycleOwner 进入活跃状态(STARTED 或 RESUMED)时,LiveData 会将最新数据发送给该观察者;当 LifecycleOwner 进入销毁状态(DESTROYED)时,LiveData 会自动移除该观察者,避免内存泄漏。
  • 数据更新通知:当调用 setValue(主线程)或 postValue(子线程)方法更新数据时,LiveData 会检查所有观察者的生命周期状态,只有处于活跃状态的观察者才会收到 onChanged 方法的调用,从而更新 UI。

整体架构与核心类

LiveData 相关的核心类主要有 LiveDataObserverLifecycleOwner 和 Lifecycle

  • LiveData:数据持有者类,负责存储数据并通知观察者数据的变化。
  • Observer:观察者接口,定义了数据变化时的回调方法。
  • LifecycleOwner:具有生命周期的组件,如 ActivityFragment,实现了该接口。
  • Lifecycle:用于跟踪组件的生命周期状态。

工作流程与源码解析

1. 创建 LiveData 对象
LiveData<String> liveData = new MutableLiveData<>();

MutableLiveData 是 LiveData 的子类,它提供了 setValue() 和 postValue() 方法来更新数据。

2. 注册观察者
liveData.observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {// 数据变化时的回调}
});

下面是 observe() 方法的源码:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");if (owner.getLifecycle().getCurrentState() == DESTROYED) {// 如果 LifecycleOwner 已经销毁,直接返回return;}LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing != null && !existing.isAttachedTo(owner)) {throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {return;}owner.getLifecycle().addObserver(wrapper);
}
  • observe() 方法首先检查是否在主线程中调用,然后检查 LifecycleOwner 的状态,如果已经销毁则直接返回。
  • 创建 LifecycleBoundObserver 对象,它是 ObserverWrapper 的子类,实现了 LifecycleEventObserver 接口,用于监听 LifecycleOwner 的生命周期变化。
  • 将 observer 和 LifecycleBoundObserver 包装对象存入 mObservers 集合中。
  • 最后将 LifecycleBoundObserver 注册到 LifecycleOwner 的生命周期观察者列表中。
3. 更新数据

可以使用 setValue() 或 postValue() 方法更新 LiveData 中的数据。

// 在主线程中更新数据
((MutableLiveData<String>) liveData).setValue("new value");// 在子线程中更新数据
((MutableLiveData<String>) liveData).postValue("new value");

setValue() 方法的源码:

@MainThread
protected void setValue(T value) {assertMainThread("setValue");mVersion++;mData = value;dispatchingValue(null);
}
  • setValue() 方法首先检查是否在主线程中调用,然后更新数据的版本号和数据值。
  • 调用 dispatchingValue() 方法通知所有观察者数据发生了变化。

postValue() 方法的源码:

protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
  • postValue() 方法用于在子线程中更新数据,它会将数据存入 mPendingData 中,并通过 ArchTaskExecutor 将更新操作切换到主线程中执行。
4. 通知观察者

dispatchingValue() 方法用于通知观察者数据发生了变化:

void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {mDispatchInvalidated = true;return;}mDispatchingValue = true;do {mDispatchInvalidated = false;if (initiator != null) {considerNotify(initiator);initiator = null;} else {for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;
}
  • dispatchingValue() 方法会遍历所有的观察者,并调用 considerNotify() 方法通知每个观察者。

considerNotify() 方法的源码:

private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//noinspection unchecked((Observer<T>) observer.mObserver).onChanged((T) mData);
}
  • considerNotify() 方法会检查观察者的活跃状态和数据版本号,如果观察者不活跃或数据版本号没有变化,则不进行通知。
  • 如果满足条件,则调用观察者的 onChanged() 方法,将最新的数据传递给观察者。

扩展追问

LiveData 的 postValue 方法用于在后台线程中更新 LiveData 的值。不过,使用这个方法时可能会出现值丢失的情况,下面结合源码深入分析其原因。

postValue 方法源码分析

postValue 方法的实现位于 LiveData 类中,以下是 postValue 方法的源码:

protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}private final Runnable mPostValueRunnable = new Runnable() {@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}setValue((T) newValue);}
};

值可能丢失的原因

1. 多线程并发调用 postValue

postValue 方法会将新值存储在 mPendingData 中,并通过 ArchTaskExecutor 将一个 Runnable 任务(mPostValueRunnable)发送到主线程执行。当在多线程环境下频繁调用 postValue 方法时,可能会出现值丢失的情况。

具体来说,postValue 方法中有一个同步块:

synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;
}

在这个同步块中,会判断 mPendingData 是否为 NOT_SET(表示没有待处理的值)。如果不是 NOT_SET,则 postTask 为 false,不会再次发送 Runnable 任务到主线程。这意味着,如果在 Runnable 任务还未执行时,又有新的 postValue 调用,新的值会覆盖 mPendingData 中的旧值,而旧值就会丢失。

例如,假设在后台线程中有两个线程同时调用 postValue 方法:

// 线程 1
liveData.postValue("value1");
// 线程 2
liveData.postValue("value2");

如果线程 2 在 mPostValueRunnable 还未执行时就调用了 postValue 方法,那么 mPendingData 中的值会从 "value1" 被覆盖为 "value2",最终 mPostValueRunnable 执行时,setValue 方法只会将 "value2" 发送给观察者,"value1" 就丢失了。

2. 主线程任务队列的延迟

postValue 方法会将 mPostValueRunnable 任务发送到主线程执行,而主线程有自己的任务队列。如果主线程比较繁忙,mPostValueRunnable 任务可能会延迟执行。在这个延迟期间,如果有新的 postValue 调用,同样会导致值丢失。

例如,当主线程正在处理大量的 UI 绘制任务时,mPostValueRunnable 任务可能会被阻塞在队列中。此时,如果有新的 postValue 调用,mPendingData 中的值会被更新,旧的值就会丢失。

解决方案

如果需要确保每个值都能被处理,可以使用 setValue 方法,但 setValue 方法必须在主线程中调用。如果需要在后台线程中更新值,可以考虑使用 MutableLiveData 的子类,自定义实现更新逻辑,确保每个值都能被正确处理。

// 在主线程中使用 setValue 方法更新值
liveData.setValue("newValue");

综上所述,LiveData 的 postValue 方法由于多线程并发调用和主线程任务队列的延迟,可能会导致值丢失。在使用时需要根据具体情况选择合适的更新方法。

总结

LiveData 的工作原理主要基于观察者模式和生命周期感知机制。

通过 observe() 方法注册观察者,将观察者与 LifecycleOwner 关联起来,当 LifecycleOwner 的生命周期状态发生变化时,LiveData 会自动处理观察者的活跃状态。

当数据更新时,LiveData 会通知所有活跃的观察者,确保只有在组件处于活跃状态时才更新 UI。这种设计使得 LiveData 具有良好的内存管理和用户体验。

http://www.dtcms.com/wzjs/356275.html

相关文章:

  • 建网站视频教程疫情防控最新政策
  • 用python做网站长沙官网seo收费标准
  • 具有品牌的上海网站建设推广软件一键发送
  • 乡村旅游网站的建设百度开车关键词
  • 中国电商集团股份有限公司搜索引擎优化seo什么意思
  • 无锡大型互联网公司简述seo
  • 沂seo网站推广思亿欧seo靠谱吗
  • 固定ip做网站路由设置蜜雪冰城推广软文
  • 网站怎么做伪静态iis7.0seo的概念
  • 网站建设系统网站自助建站系统seo云优化是什么意思
  • 北京上地做网站goole官网
  • 设计素材网站图片应用市场
  • 网站安装百度商桥网络广告创意
  • 织梦网站名称如何做网销
  • 网站建设利益分析简述网站推广的意义和方法
  • 沈阳市城市建设局网站市场营销案例
  • 呼和浩特做网站的地方网站模板
  • html5企业网站开发怎样创建一个网站
  • 资阳网站建设 xiuweb网址查询地址查询
  • 分类信息网站建设方案简单的html网页制作
  • 深圳做网站建设和维护专员管理层做关键词优化
  • 简单网站制作成品网站生成app
  • 泰州做网站的seo搜索引擎工具
  • 西安模板网站建设套餐搜索引擎名词解释
  • 网站建设分为几个阶段免费发帖推广的平台
  • 做竞品分析去哪个网站可以发外链的平台
  • 网站建设唐山网络服务
  • 论坛上怎么做网站优化百度电话人工服务
  • 东莞网站建设seo优化互联网品牌的快速推广
  • 石家庄企业制作网站前端性能优化有哪些方法