目录
ViewModel与LiveData的介绍
●ViewModel
ViewModel故名思议是连接View(视图)与Model(数据)之间的桥梁,Jetpack中的ViewModel可以我们降低以前Activity中视图和数据之间的耦合,我们使用ViewModel需要继承androidx.lifecycle.ViewModel如下,其中的onCleared是当与之相关的Activity被销毁是会回调的方法,我们可以在这里进行数据的释放等操作
public class MyViewModel extends ViewModel {
@Override
protected void onCleared() {
super.onCleared();
}
}
●LiveData
LiveData可以翻译为活着的数据,我们可以通过它来包装数据,进而可以对数据的改变进行监听,结合ViewModel可以很大程度的降低View(视图)与Model(数据)之间的耦合度。
ViewModel与LiveData的使用
1.创建ViewMdel
public class MyViewModel extends ViewModel {
@Override
protected void onCleared() {
super.onCleared();
}
}
2.ViewMdel中添加LiveData
这里我们使用的是系统提供的MutableLiveData
public class MyViewModel extends ViewModel {
private MutableLiveData<String> mName;
public MutableLiveData<String> getName() {
if(mName == null){
mName = new MutableLiveData<>();
}
return mName;
}
@Override
protected void onCleared() {
super.onCleared();
}
}
3.Avticity中绑定ViewMdel并监听LiveData
我们通过ViewModelProvider获取并绑定ViewModel,然后通过获取到的ViewModel获取LiveData,然后通过observe方法对LiveData进行监听,这里我们还添加了一个按钮和一个TextView,当按钮点击的时候我们修改LiveData的值,然后在LiveData的监听方法中将改变后的值赋给TextView,代码如下
public class MainActivity extends AppCompatActivity {
private TextView tv;
private Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
bt = (Button) findViewById(R.id.bt);
//绑定ViewModel
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
//获取LiveData
MutableLiveData<String> name = myViewModel.getName();
//对LiveData进行监听
name.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
tv.setText(s);
}
});
bt.setOnClickListener(v->{
name.setValue("数据改变");
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Button
android:id="@+id/bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
ViewModel与LiveData的部分源码解析
●ViewModel
根据ViewModel的创建过程我们知道,ViewModel的创建需要ViewModelProvider,我们查看ViewModelProvider的源码发现它的构造函数需要传入ViewModelStoreOwner
/**
* Creates {@code ViewModelProvider}. This will create {@code ViewModels}
* and retain them in a store of the given {@code ViewModelStoreOwner}.
* <p>
* This method will use the
* {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory}
* if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a
* {@link NewInstanceFactory} will be used.
*/
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
而我们在MainActivity中调用ViewModelProvider的构造函数时传入的是this,是因为MainActivity继承自了AppCompatActivity而AppCompatActivity又间接继承了ComponentActivity,而ComponentActivity实现了ViewModelStoreOwner接口,因此我们可以将MainActivity的引用作为参数进行传递
接下来我们再看看我们通过查看ViewModelStoreOwner的源码发现,ViewModelStoreOwner接口只有一个getViewModelStore()它返回了ViewModelStore
public interface ViewModelStoreOwner {
/**
* Returns owned {@link ViewModelStore}
*
* @return a {@code ViewModelStore}
*/
@NonNull
ViewModelStore getViewModelStore();
}
我们再查看ViewModelStore的源码发现,它内部对于ViewModel的存储是通过Map实现的
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* Clears internal storage and notifies ViewModels that they are no longer used.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
所以我们通过ViewModelProvider创建ViewModel的时候是先查找Map中是否有实例,如果有就取出没有则创建并存储
●LiveData
我们通过查看LiveData的observe方法发现,它是需要LifecycleOwner作为参数传入的
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
而由于MainActivity的间接父类ComponentActivity已经实现了该接口,因此我们可以将当前Activity的引用作为参数传入,另外我们之前的一篇文章(Android Jetpack之LifeCycle的使用
)已经讲解了通过LifecycleOwner可以实现对Activity生命周期的监听,因此我们可以得知LiveData也是可以监听Activity的生命周期的,我们在LiveData的observe方法源码中也可以看出这一点,它先判断了当前是否在主线程中执行,然后又判断了当前所在的Activity(也可以是Fragment等)是否已经销毁了,如果销毁了就不执行下面的逻辑了,因此使用LiveData也会让我们少处理一些逻辑,因为它内部已经进行判断了
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
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);
}
网友评论