jetpack学习(三)——LiveData&ViewModel
LiveData
使用 LiveData 的优势
确保界面符合数据状态
LiveData 遵循观察者模式。当生命周期状态发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。观察者可以在每次发生更改时更新界面,而不是在每次应用数据发生更改时更新界面。
不会发生内存泄露
观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
不会因 Activity 停止而导致崩溃
如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。
不再需要手动处理生命周期
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
数据始终保持最新状态
如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
适当的配置更改
如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
共享资源
您可以使用单一实例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象。
使用 LiveData 对象
- 1.创建 LiveData 实例以存储某种类型的数据。这通常在 ViewModel 类中完成。
- 2.创建可定义 onChanged() 方法的 Observer 对象,该方法可以控制当 LiveData 对象存储的数据更改时会发生什么。通常情况下,您可以在界面控制器(如 Activity 或 Fragment)中创建 Observer 对象。
- 3.使用 observe() 方法将 Observer 对象附加到 LiveData 对象。observe() 方法会采用 LifecycleOwner 对象。这样会使 Observer 对象订阅 LiveData 对象,以使其收到有关更改的通知。通常情况下,您可以在界面控制器(如 Activity 或 Fragment)中附加 Observer 对象。
创建LiveData对象<相关依赖略>
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName() {
if (currentName == null) {
currentName = new MutableLiveData<String>();
}
return currentName;
}
// Rest of the ViewModel...
}
观察 LiveData 对象
public class NameActivity extends AppCompatActivity {
private NameViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
model = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
nameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.getCurrentName().observe(this, nameObserver);
}
}
如下为AS自动创建带有ViewModel的Fragment,注意ViewModel直接在onActivityCreated初始化
public class BlankFragment extends Fragment {
private BlankViewModel mViewModel;
public static BlankFragment newInstance() {
return new BlankFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.blank_fragment, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(BlankViewModel.class);
// TODO: Use the ViewModel
}
}
更新LiveData
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
model.getCurrentName().setValue(anotherName);
}
});
ViewModel<相关依赖略>
实现 ViewModel
创建MyViewModel
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
访问
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
databinding+viewmodel+livedata结合使用
activity_view_model.xml
直接可以再布局文件中引用相关的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>
<import type="android.view.View.OnClickListener"/>
<import type="com.hwp.databindingdemo.NameViewModel"/>
<variable
name="mode"
type="NameViewModel" />
<variable
name="myClickListener"
type="OnClickListener" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.ViewModelActivity">
<TextView
android:text="@{mode.name}"
tools:text="name"
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{mode.nameList[0]}"
tools:text="nameList"
android:id="@+id/tv_name_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:onClick="@{myClickListener}"
android:id="@+id/btn_01"
android:text="按钮一"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:onClick="@{myClickListener}"
android:id="@+id/btn_02"
android:text="按钮二"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
ViewModelActivity.java
public class ViewModelActivity extends AppCompatActivity implements View.OnClickListener {
private NameViewModel nameViewModel;
private ActivityViewModelBinding viewModelBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModelBinding= DataBindingUtil.setContentView(this,R.layout.activity_view_model);
viewModelBinding.setMyClickListener(this);
nameViewModel=ViewModelProviders.of(this).get(NameViewModel.class);
//databing设置viewmodel
viewModelBinding.setMode(nameViewModel);
viewModelBinding.setLifecycleOwner(this);
//使用databing后,如下方法都可以省略了,更加便捷了
/* nameViewModel.getName().observe(this, new Observer<String>() {
@Override
public void onChanged(String str) {
}
});
nameViewModel.getNameList().observe(this, new Observer<List<String>>() {
@Override
public void onChanged(List<String> strings) {
}
});*/
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_01:
nameViewModel.getName().setValue("我是值");
// viewModelBinding.setMode(nameViewModel);
break;
case R.id.btn_02:
List<String> list=new ArrayList<>();
list.add("值一");
list.add("值二");
list.add("值三");
nameViewModel.getNameList().setValue(list);
// viewModelBinding.setMode(nameViewModel);
break;
}
}
}
NameViewModel.java
public class NameViewModel extends ViewModel {
private MutableLiveData<String> mName;
private MutableLiveData<List<String>> mNameList;
public MutableLiveData<String> getName(){
if(mName==null){
mName=new MutableLiveData<>();
}
return mName;
}
public MutableLiveData<List<String>> getNameList(){
if(mNameList==null){
mNameList=new MutableLiveData<>();
}
return mNameList;
}
}
网友评论