一直以来,Android开发都充斥了大量的不规范的操作和重复代码,比如生命周期的管理,开发过程的重复,项目架构的选择等等。谷歌IO大会上,Google官方向推出了 Jetpack,旨在让开发者们能够更好,更快,更规范地开发出优质应用。
lifecycle
- DataBinding
- Navigation
- Room
- WorkManger
- Paging
1. 作用
- 用以解决的痛点
- 瞬态数据丢失
- 异步调用内存泄漏
- 类膨胀提高维护难度和测试难度
- viewModel是什么?
- 它是介于View(视图)和Model(数据模型)之间的桥梁
- 使视图和数据能够分离,也能保持通信
官方解释:ViewModel类是被设计用来以可感知生命周期的方式存储和管理 UI 相关数据,ViewModel中数据会一直存活即使 activity configuration发生变化,比如横竖屏切换的时候。
2. 使用
1.gradle依赖
//引入AndroidX吧,替换掉support包
implementation 'androidx.appcompat:appcompat:1.0.2'
def lifecycle_version = "2.0.0"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
2. ViewModel 简单应用
public class MyViewModel extends ViewModel {
public int number;
}
public class MainActivity extends FragmentActivity {
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.tv_content);
//构建ViewModel实例
MyViewModel viewModel = new ViewModelProviders(this,new ViewModelProvider
.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);
mTextView.setText(String.valueOf(viewModel.number))
findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击按钮 更新number数据
mTextView.setText(String.valueOf(++viewModel.number));
}
});
}
}
编译后,以上在屏幕旋转之后数据任然存在不会丢失,是应为ViewModel的特性可以让它独立于配置变化。
注意:
- 不要向ViewModel 中传入Context,会导致内存泄漏。
- 如果必须使用Context,使用AndoridViewModel中的Application。
3. 使用ViewModel + LiveData 在 ViewModel中数据变化时通知页面
LiveData的优势
- 确保界面符合数据状态
- 不会反生内存泄漏
- 不会因Activity 停止而导致崩溃
- 不再需要手动处理生命周期
- 数据始终保持最新状态
- 适当的配置更改
- 共享资源
public class MyViewModel extends ViewModel {
public final MutableLiveData<Integer> currentSecond = new MutableLiveData<>();
public MutableLiveData<Integer> getCurrentSecond(){
if(currentSecond==null){
currentSecond = new MutableLiveData<>();
currentSecond.setValue(0);
}
returen currentSecond;
}
}
public class MainActivity extends FragmentActivity {
private TextView mTextView;
private MyViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.tv_content);
//构建ViewModel实例
viewModel = new ViewModelProviders(this,new ViewModelProvider
.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);
mTextView.setText(String.valueOf(viewModel.getCurrentSecond().getValue()));
// viewModel 中的数据变化会动态回调
viewModel.getCurrentSecond().observe(this,new Observer<Integer>(){
@Override
public void onChange(Integer data){
mTextView.setText(String.valueOf(data));
}
});
startTime();
}
private void startTime(){
new Timer().schedule(new TimerTask(){
@Override
public void run(){
Integer value = viewModel.getCurrentSecond().getValue();
// 非UI线程 postValue、UI线程 setValue
viewModel.getCurrentSecond().postValue(value+1);
}
},1000,1000);
}
}
4. 使用ViewModel + LiveData 实现Fragment间通信
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 实现通信的重点是 使用 getActivity()
model = new ViewModelProviders(getActivity(),new ViewModelProvider
.AndroidViewModelFactory(getApplication())).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 实现通信的重点是 使用 getActivity()
SharedViewModel model = new ViewModelProviders(getActivity(),new ViewModelProvider
.AndroidViewModelFactory(getApplication())).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// Update the UI.
});
}
}