Lifecycles
管理您的 Activity 和 Fragment 生命周期
如何使用
来看接口
LifecycleObserver //如果实现这个 接口 需要使用注解方式来来监听生命周期的变化
GenericLifecycleObserver //如何实现这个接口 当生命周期变化 调用 onStateChanged 方法
FullLifecycleObserver //这个接口是全部的生命周期函数
//使用该方法添加观察者
getLifecycle().addObserver(new MyObserver());
分析该生命周期是如何回调到的
有一个LifecycleRegistry 的类 实现了 Lifecycle 接口
那LifecycleRegistry 对象是如何在Activity生命变化的时候通知到 LifecycleObserver
LifecycleRegistry 的实例化在 Fragment 中 当Fragment 生命周期变化 通知到 LifecycleObserver
LiveData
在底层数据库更改时通知视图
代码分析
//添加 观察者 内部使用 getLifecycle().addObserver(); 注册生命周期
liveData.observe(lifecycleOwner, new Observer() {
@Override
public void onChanged(@Nullable Object o) {
}
});
liveData.setValue("hello");
原理
liveData.observe 注册生命周期回调 添加 ObserverWrapper 到mObservers 中
当调用setValue 方法后 他会调用dispatchingValue 方法 该方法会遍历 mObservers (它是个Map) 取出 value
该value是 ObserverWrapper 对象 然后 调用 considerNotify 方法 通知 观察者 回调到 onChanged 方法
ViewModel
以注重生命周期的方式管理界面相关的数据
为什么屏幕旋转后Activity 重新创建了 而ViewModel 不会重新创建
https://juejin.im/post/5c88fac76fb9a049c16013c6
答:因为在系统在调用 activity 的 onDestory 前 首先 调用onRetainNonConfigurationInstance 方法 保存 Object 对象到ActivityClientRecord 中的lastNonConfigurationInstances 中 当Activity重新 创建的时候 系统调用activity的attach 后 把 r.lastNonConfigurationInstances 对象传递给 activity 因此NonConfigurationInstances 不会重新 它里面的viewModelStore也不会重新创建 因此ViewModel 不会重新创建
//Actvity 中的方法
public Object onRetainNonConfigurationInstance() {
return null;
}
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
代码简单分析
//ViewModelProviders.of(this).get(MyViewMode.class) activity通过反射创建MyViewMode 对象然后保存到viewModelStore 中 viewModelStore 是一个Map 对象
MyViewMode myViewMode = ViewModelProviders.of(this).get(MyViewMode.class);
// 获取LiveData 添加 观察者 当liveData 调用 setValue是 会回调onChanged 方法
myViewMode.getTableLiveData().observe(this, new Observer() {
@Override
public void onChanged(@Nullable Object o) {
}
});
ViewModel的状态保存
当系统杀死app 进程后 ViewModel 数据如何保存
当我们想缓存数据时ViewModel 如何保存数据
DataBinding
dataBinding {
enabled true
}
对布局文件使用 layout 和 data 标签
当AS 编译完成后会自动生成 xml文件名Binding 类
该类如何使用:
ActivityLivedataBinding binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_livedata);
binding.textView3.setText("xxxx");
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.constraint.ConstraintLayout>
</layout>
如何把ViewModel 与 控件绑定
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="data"
type="com.zgt.myapplication.viewmodel.MyViewModel" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button3"
android:text="Button"
android:onClick="@{()->data.add()}"
/>
<TextView
android:id="@+id/textView3"
android:text="@{String.valueOf(data.number)}"
/>
</android.support.constraint.ConstraintLayout>
</layout>
java 代码
ActivityLivedataBinding binding;
MyViewModel viewModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_livedata);
binding.textView3.setText("xxxx");
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
binding.setData(viewModel);
binding.setLifecycleOwner(this);
}
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> number;
public MutableLiveData<Integer> getNumber() {
if (number == null){
number = new MutableLiveData<>();
number.setValue(0);
}
return number;
}
public void add(){
number.setValue(number.getValue()+1);
}
}
在Fragment 中使用
public class MyFragment extends DialogFragment {
ActivityLivedataBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.activity_livedata,container,false);
binding = DataBindingUtil.bind(root);
return root;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
binding.setData(viewModel);
binding.setLifecycleOwner(this);
}
}
//MyFragment fragment = new MyFragment(); //fragment.show(getSupportFragmentManager(),MyFragment.class.getSimpleName());
// Lifecyle的版本,现在最新的是1.1.1
def lifecycle_version = "1.1.1"
// ViewModel 和 LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
// 仅用 ViewModel
implementation "android.arch.lifecycle:viewmodel:$lifecycle_version"
// 仅用 LiveData
implementation "android.arch.lifecycle:livedata:$lifecycle_version"
// 仅仅支持Lifecycle, 不包含LifeModel和LiveData
implementation "android.arch.lifecycle:runtime:$lifecycle_version"
annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version"
// 如果用的是java8使用以下的依赖
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"
// LiveData 的 ReactiveStreams插件
implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version"
// LiveData测试
testImplementation "android.arch.core:core-testing:$lifecycle_version"
//ArchTaskExecutor 可以让 任务运行在 UI线程中 还是 子线程中
ArchTaskExecutor.getInstance().executeOnMainThread