Databinding:单双向数据绑定
Databinding:动态数据更新
Lifecycle讲解
livedata源码分析
ViewModel源码+最终组合使用
前言
ViewModel一般都是和livedata一起使用,主要目的其实就是为了解耦,livedata中通过lifecycle根据生命周期做一些事情,ViewModel控制着数据,结合databinding,相互配合使用,ViewModel控制着数据,通过反射创建并在store中统一进行管理
这里需要说一下,ViewModel在2.1.0之后废弃了ViewModelProviders这个类,统一使用ViewModelProvider,其实吧,说白了就是把ViewModelProviders中的of方法拆开了。
老版本的创建
之前是这么用的,眼熟吧。
TestViewModle viewModle = ViewModelProviders.of(this).get(TestViewModle.class);
新版本的创建
废弃后通过ViewModelProvider类实现:
通过构造方法可以看到需要传入一个owner和一个工厂,有啥用呢
1、owner用来得到一个ViewModelStore,意如其名,就是用来管理ViewModel的
2、factory当然就是为了制造ViewModel的了
ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory;
现在的生成方法:
1、为什么要通过AndroidViewModelFactory,因为老版本的of中就是用的这个方法。。。这个理由是不是很骚气。。。
2、使用get方法去获取modle对象
TestViewModle viewModle = new ViewModelProvider(this , ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(TestViewModle.class);
get方法其实就是为了复用ViewModel,ViewModel都是有构造中传入的owner成成的store统一管理的,最后调用了create方法,通过反射创建出自定义的TestViewModle对象,并返回。
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
return (T) viewModel;
} else {
if (viewModel != null) {
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
viewmodel
这个onCleared可以用来当viewmodel不在被使用的时候,做一些销毁的工作,防止内存泄漏
class TestViewModle extends ViewModel {
@Override
protected void onCleared() {
super.onCleared();
}
}
最后来一个组合使用
布局文件
data中的三个类:1、bean类;2、交互类,一般如点击事件;3、请求+数据处理操作类;算是标配吧;
这个bean类可以写在布局文件里,也可以在ViewModel中通过泛型创建,方便拓展
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="user"
type="com.example.myapplication.bean.User" />
<variable
name="present"
type="com.example.myapplication.UserPresent" />
<variable
name="viewmodel"
type="com.example.myapplication.UserViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/xiaoguo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录界面" />
//把数据绑定到viewmodel中的requestData中去,等待网络请求使用
<EditText
android:id="@+id/edit_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:afterTextChanged="@{viewmodel.afterTextChange}"
android:hint="输入框"/>
<Button
android:id="@+id/first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{(view)->present.myClick(view ,user)}" //点击事件
android:text="@{user.firstName}" />
<Button
android:id="@+id/last_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{(view)->present.myClick(view ,user)}"//点击事件
android:text="@{user.lastName}" />
</LinearLayout>
</layout>
UserViewModel类
1、这个类用来作为数据控制类,桥接view和model,通过livedata操作数据
2、布局中EditText输入的数据保存到requestData 中,在调用requestData()方法的时候,将结果通过userData传递给view层
public class UserViewModel extends ViewModel {
MutableLiveData<String> requestData = new MutableLiveData<>();//保存文本输入的数据
MutableLiveData<User> userData = new MutableLiveData<>();//将数据传给view层
//模拟网络请求
public void requestData() {
User user = new User("jiang", requestData.getValue(), 100);
userData.setValue(user);
}
@Override
protected void onCleared() {
super.onCleared();
}
//接受输入的数据保存到requestData中去,等待请求使用
public void afterTextChange(Editable s) {
requestData.setValue(s.toString());
}
}
主类
//实现点击类UserPresent
public class MainActivity extends AppCompatActivity implements UserPresent {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建dataBinding
dbBinding = DataBindingUtil.setContentView(this, R.layout.activity_db);
//绑定点击事件
dbBinding.setPresent(this);
//初始化bean类数据并绑定到dataBinding里
dbBinding.setUser(new User("点击请求","结果",100));
//创建并绑定viewmodel
dbBinding.setViewmodel(new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(UserViewModel.class));
//创建viewmodel中的数据监听器并绑定到dataBinding中去
dbBinding.getViewmodel().userData.observe(this, new Observer<User>() {
@Override
public void onChanged(User user) {
//如果数据有修改,更新要改的地方。
dbBinding.getUser().setLastName(user.getLastName());
}
});
}
//重写点击方法,调用请求
@Override
public void myClick(View view, User user) {
dbBinding.getViewmodel().requestData();
}
}