微信手机网站案例,北京网站建设服务器维护,怎么做相册的网站,零基础编程学pythonJetpack的分类
1. DataBinding#xff1a;以声明方式将可观察数据绑定到界面元素#xff0c;通常和ViewModel配合使用。
2. Lifecycle#xff1a;用于管理Activity和Fragment的生命周期#xff0c;可帮助开发者生成更易于维护的轻量级代码。
3. LiveData: 在底层数据库更…Jetpack的分类
1. DataBinding以声明方式将可观察数据绑定到界面元素通常和ViewModel配合使用。
2. Lifecycle用于管理Activity和Fragment的生命周期可帮助开发者生成更易于维护的轻量级代码。
3. LiveData: 在底层数据库更改时通知视图。它是一个可观察的数据持有者与常规observable不同LiveData是生命周期感知的。
4. Navigation:处理应用内导航。
5. Paging:可以帮助开发者一次加载和显示小块数据按需加载部分数据可减少网络带宽和系统资源的使用。
6. Room:友好、流畅的访问SQLite数据库。它在SQLite的基础上提供了一个抽象层允许更强大的数据库访问。
7. ViewModel: 以生命周期的方式管理界面相关的数据通常和DataBinding配合使用为开发者实现MVVM架构提供了强有力的支持。
8. WorkManager: 管理Android的后台的作业即使应用程序退出或设备重新启动也可以运行可延迟的异步任务。Android 标准架构框架图
Android官方架构部分的知识 https://developer.android.google.cn/topic/architecture/intro?hlzh-cn
ViewBindingDataBinding篇
ViewBinding介绍和使用
大家还是不要把ViewBinding和DataBinding这两个不要混淆了. ViewBindling 这是一个负责绑定View到代码减少 findViewId降低空引用资源ID错误。使用起来也较为简单 流程是 第一、 在 app模块下的build.gradle.kts下,打开使用ViewBinder的开关:
Android{
…
buildFeatures {ViewBinding true}
}第二就是需要在使用的Activity、fragment、view里面去初始化一下inflate“
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)}
}第三步就可以直接引用使用了
binding.button.texthelloworld注意 viewBinding 目前能够支持所有Xml的控件进行自动绑定 包含Activity、Fragment以及其他View等。
ViewBinding原理
开启后会自动生成【xml的文件名 自动大驼峰】Binding.kt 文件。例如ActivityMainBinding.kt。可以看一下自动生成文件代码我只看inflate最后执行的部分
public static ActivityMainBinding bind(NonNull View rootView) {
int id;
id R.id.tv1;
TextView tv1 ViewBindings.findChildViewById(rootView, id);if (tv1 null) {
break missingId;
}
id R.id.tv2;
TextView tv2 ViewBindings.findChildViewById(rootView, id);
if (tv2 null) {
break missingId;
}
return new ActivityMainBinding((ConstraintLayout) rootView, tv1, tv2);}
}可以看到自动生成的代码里会把XML里控件的每个id都会塞进去并且调findViewById进行绑定。
DataBinding的介绍和使用
Android 开发中体现 MVVM 架构思想的 Data Binding其核心是 观察者模式 的特定实现。首先它有三个主要的实体
Data与 View 相关的数据它可以是 View 的可观察者对象View展示给用户的视图如果有交互功能且能更新数据它可以是 Data 的可观察者对象ViewDataBinding连接 Data 和 View 的中介当 Data 或 View 作为可观察者对象时它充当可观察者对象的代理。假如当我们写了一个名为 demo.xml 的 Data Binding 的 layout 文件后编译工具会生成一个相应的类——DemoBinding它的原型就是 ViewDataBinding。我们通常通过 DataBindingUtil.inflate(inflater, R.layout.demo, container, false) 来实例化的 DemoBinding 对象即 ViewDataBinding。
主要是三个方面的功能 • 将特定的 View 与特定的 Data 进行绑定便于模块化 • View 自动感知和响应 Data 的变化使得处理数据的业务层不必关心 View 的状态便于解耦 • Data 也可以自动同步带有交互功能的 View 对数据的修改使得 UI 层的交互不必担心数据是否能同步 View 状态的问题仍然便于解耦
使用类似ViewBinding: 第一是在 app模块下的build.gradle.kts下,打开使用ViewBinder的开关:
Android{
…
buildFeatures {DataBinding true}
}第二就可以直接在需要使用Xml文件里使用就行了但是前提现有已经新简的Data类
class User(var firstName: String, var lastName: String) {}
?xml version1.0 encodingutf-8?
layout xmlns:androidhttp://schemas.android.com/apk/res/androiddata variable nameuser typecom.example.User//data LinearLayout android:orientationvertical android:layout_widthmatch_parent android:layout_heightmatch_parent TextView android:layout_widthwrap_content android:layout_heightwrap_content android:text{user.firstName}/ TextView android:layout_widthwrap_content android:layout_heightwrap_content android:text{user.lastName}/ /LinearLayout/layout基础用法很简单 但是这只是单项View-Data绑定。 比较好的功能是 它还能帮助我们做到通过感知Data的局部变量来进行局部刷新还有可以可以绑定View进行双向绑定。使用方法就是将Data转化成observe 对象并且添加Bindable 的竹节通过notifyPropertyChanged方法来达成局部刷新如下
public class DemoData extends BaseObservable {private int element;
// 定义其它成员省略
Bindablepublic int getElement() {return this.element;}
public void setElement(int e) {this.element e;notifyPropertyChanged(BR.element);}
// 省略其它成员操作
}ViewModel篇
viewModel 的使用 viewModel继承子类使用 数据存储在内存中可以和acitivty 生命周期进行绑定也独立于ActivityonSaveInstanceState(Bundle) 存储的数据仅在当前应用进程哪有效 当退出重新进入 Bundle重新恢复成初始状态。或者在 OnStop中保存永久性数据
存储作用域 实例化 ViewModel 时您会向其传递实现 ViewModelStoreOwner 接口的对象。它可能是 Navigation 目的地、Navigation 图表、activity、fragment 或实现接口的任何其他类型。然后ViewModel 的作用域将限定为 ViewModelStoreOwner 的 Lifecycle。它会一直保留在内存中直到其 ViewModelStoreOwner 永久消失。 有一系列类是 ViewModelStoreOwner 接口的直接或间接子类。直接子类为 ComponentActivity、Fragment 和 NavBackStackEntry。如需查看间接子类的完整列表请参阅 ViewModelStoreOwner 参考文档。 当 ViewModel 的作用域 fragment 或 activity 被销毁时异步工作会在作用域限定到该 fragment 或 activity 的 ViewModel 中继续进行。这是持久性的关键。 如需了解详情请参阅下文有关 ViewModel 生命周期的部分
我这里不去赘述 如何使用它 我曾在上一家公司中对的Alios系统平台 使用TS语言设计了一个跟viewModel类似的 组件库DataManager .主要的设计原则是观察者绑定和职责分离原则。 本质上来讲ViewModel 就是一个独立的数据储存类 设计者在里面做了跟Activity的destory来消亡的【非因为配置改变导致的destory】其实也可以做到完全独立消亡由开发者自己决定 这样就会很有趣了多个activty可以共一个ViewModel实例.只是里面做了一些对象传递的封装就可以和LiveData进行配合使用。
ViewModelStore用于存储ViewModel实例的类内部持有一个HashMap保存实例ViewModelProvider会将创建好的ViewModel实例保存到ViewModelStore中之后再需要此类ViewModel的实例时就直接从中读取。ViewModelProvider.Factory前文已经提到这是用于创建ViewModel实例的工厂ViewModelProvider当需要ViewModel的实例又在ViewModelStore中没有找到对应实例时就会调用工厂的create方法创建。CreationExtras前文也已提到它用于在创建ViewModel实例时从外界向构造过程传递参数内部持有一个MutableMap以key-value的形式存储和查找参数
ViewModelStore中的HashMap 设计应该是至少两层以上的在当初我设计的空间中这里用的两层 并且因为是量产项目的原因 加了一个些状态机key值进行了耦合。 Android官方是直接保存的ViewModel的对象这样就只有一层了。 每个Acitivty都会有一个ViewModelStoreOwner 这样在开发者做项目的时候就不需要关系每个Activity的获取ViewModel的时候就是绑定的哪一个。 public class ComponentActivity extends androidx.core.app.ComponentActivity implements … // 实现了 ViewModelStoreOwner 接口 ViewModelStoreOwner, …{ private ViewModelStore mViewModelStore; // 重写了 ViewModelStoreOwner 接口的唯一的方法 getViewModelStore() NonNull Override public ViewModelStore getViewModelStore() { if (getApplication() null) { throw new IllegalStateException(Your activity is not yet attached to the “Application instance. You can’t request ViewModel before onCreate call.”); } ensureViewModelStore(); return mViewModelStore; } ViewModelProvider 的构造方法时 获取 ViewModelStore 对象时实际调用了 MainActivity#getViewModelStore() 而 getViewModelStore() 实现在 MainActivity 的父类 ComponentActivity 中。 在返回 mViewModelStore 对象之前调用了 ensureViewModelStore() void ensureViewModelStore() { if (mViewModelStore null) { NonConfigurationInstances nc (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc ! null) { // Restore the ViewModelStore from NonConfigurationInstances mViewModelStore nc.viewModelStore; } if (mViewModelStore null) { mViewModelStore new ViewModelStore(); } } } - onRetainNonConfigurationInstance 方法和 getLastNonConfigurationInstance 是成对出现的跟 onSaveInstanceState 机制类似只不过它是仅用作处理配置更改的优化。
- 返回的是 onRetainNonConfigurationInstance 返回的对象Activity 在因配置更改而销毁重建过程中会先调用 onRetainNonConfigurationInstance 保存 viewModelStore 实例。 在重建后可以通过 getLastNonConfigurationInstance 方法获取之前的 viewModelStore 实例。
另外我們可以看一下 mViewModelStore 销毁的时机其实是在生命周期的判断Lifecycle.Event.ON_DESTROY 被摧毁并且 判断是否是配置改变引起的isChangingConfigurations()来进行区分
getLifecycle().addObserver(new LifecycleEventObserver() {Overridepublic void onStateChanged(NonNull LifecycleOwner source,NonNull Lifecycle.Event event) {if (event Lifecycle.Event.ON_DESTROY) {// Clear out the available contextmContextAwareHelper.clearAvailableContext();// And clear the ViewModelStoreif (!isChangingConfigurations()) {getViewModelStore().clear();}}}});...}ViewModel 出现之前Activity 可以使用 onSaveInstanceState() 方法保存然后从 onCreate() 中的 Bundle 恢复数据但此方法仅适合可以序列化再反序列化的少量数据IPC 对 Bundle 有 1M 的限制而不适合数量可能较大的数据如用户信息列表或位图。 ViewModel 的出现完美解决这个问题。
LiveData篇
通常情况下LiveData都是配合viewModel使用在某个具体的ViewModel类中定义LiveData数据然后在对应的Activity或Fragment中观察LiveData数据的变化LiveData的使用使得我们不再将数据保存在Activity或Fragment中减轻了Activity或Fragment的工作量使得Activity或Fragment只负责界面的管理和显示而不在保存数据也不会受到数据的影响。但是也可以使用oberveForever不绑定生命周期 那就需要自己手动管理它的消亡。 核心方法
通过 observe(owner,observer) 向 LiveData 注册观察者 • 通过 observe(owner,observer) 向 LiveData 注册观察者并且把 observer 包装成一个 LifecycleBoundObserver它是一个具有生命周期边界的观察者因为这个观察者只有当宿主处于 STARTED 或者 RESUMED 状态的它才会接收数据其他时候它是不会接收数据的。 • 把包装好的 Observer 注册到 Lifecycle 当中handlerLifecycleEvent(event) 利用 Lifecycle 能力它能感知宿主生命周期能力的关键地方。注册时和宿主每次生命周期变化都会回调 onStateChanged() 方法刚进去的时候会触发方法的同步。 • 会判断这个事件宿主是否被销毁了从而主动地把 Observer 从 LiveData 中移除掉流程结束。如果不是 DESTORY说明宿主当前的状态发生了变化它会触发 activeStateChanged(boolean newActive) 方法它会判断当前 Observer 是否处于活跃的状态如果宿主的状态为 STARTEDRESUMED 则会分发最新数据到每个观察者。 • 进而调用 dispatchingValue(ObserverWrapper) 分发数据如果 ObserverWrapper 为空则分发数据给 liveData 中存储的所有观察者如果不为空则分发数据给该 Observer。 • considerNotify(ObserverWrapper) 中先判断观察者所在的宿主不活跃则不分发接着如果 observer 的 mLastVersion 大于或等于 LiveData 的 mVersion 则不分发防止重复发送数据最后通过 observer.mObserver.onChanged((T) mData) 分发数据同步 mVersion 数据。 • 那么 LiveData 先发送数据后注册的 Observer 能接收到数据吗 答案是可以的。
普通消息的发送 • postValue() 发送一条数据它可以在任意线程使用的里面实际使用了 Handler.post 先把这个事件发送到主线程然后在调用 setValue() 发送数据 • setValue() 代表着 LiveData 发送数据每发送一次 mVersion另外 LifecycleBoundObserver 中也有一个它代表这个 Observer 接收了几次数据在分发数据的时候这两个 version 会进行比对防止数据重复发送 • setValue() 里面也会触发 dispatchingValue(ObserverWrapper)ObserverWrapper 为 nulldispatchingValue() 它会遍历 Observer 集合里面所有观察者然后逐一调用 considerNotify(ObserverWrapper) 去做消息的分发。
此外LiveData和 Room配合使用 时候 LiveData 就是为了简化room 的Dao查询对象到 viewModel的过程 返回LiveData对象 查询数据的操作就不需要自己去创建后台线程 。 LiveData能够自动完成。至于为什么Room的查询使用LiveData对象就不需要自己起子线程。 是因为 当liveData做返回对象的时候room的 查询方法会多使用一个ComputableLiveData类 这里面会判断是否有子线程如果没有自己会自动起一个子线程去查询普通类型就会直接走SupportSQLiteDatabase#query(SupportSQLiteQuery)方法看下面代码
并且使用LiveData.observe.能够添加观察者 绑定fragment周期和数据的更新只要LiveData的数据发生变化 就会实时刷新 普通数据类型的查询
/*** Wrapper for {link SupportSQLiteDatabase#query(SupportSQLiteQuery)}.** param query The Query which includes the SQL and a bind callback for bind arguments.* return Result of the query.*/public Cursor query(SupportSQLiteQuery query) {assertNotMainThread();return mOpenHelper.getWritableDatabase().query(query);}使用LiveData作为返回值时用到了ComputableLiveData类此类在构造的时候就将RoomDatabase中的mQueryExecutor传入了。如果在构造的时候没有传入自定义的Executor那么会自动生成一个。会走这个方法 if (mQueryExecutor null) {mQueryExecutor ArchTaskExecutor.getIOThreadExecutor();}