LiveData
Livedata
是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。活跃状态是指OnResume和Onstart状态。Livedata是一种响应式编程,设置观察者。
LiveData的优势
- 确保界面符合数据状态,当底层数据发生变化时,LiveData 会通知 Observer 对象。这样一来,无需在每次应用数据发生变化时更新界面,因为观察者会完成更新。
- 不会发生内存泄漏,观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
public void observe(@NonNull LifecycleOwner owner, //Lifecycle对象
@NonNull Observer<? super T> observer)
- 不会因 Activity 停止而导致崩溃,如果观察者的生命周期处于非活跃状态(如返回堆栈中的 activity),它便不会接收任何 LiveData 事件。
- 不再需要手动处理生命周期,界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
- 数据始终保持最新状态,如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
- 适当的配置更改如果由于配置更改(如设备旋转)而重新创建了 activity 或 fragment,它会立即接收最新的可用数据。
LiveData
一般结合ViewModel
使用,注册多个观察者。这里先看看其基本使用。
LiveData使用
- 创建 LiveData 的实例以存储某种类型的数据,数据类型是任意的
- 创建可定义 onChanged() 方法的 Observer 对象,该方法可以控制当 LiveData 对象存储的数据更改时会发生什么。通常情况下,您可以在界面控制器(如 activity 或 fragment)中创建 Observer 对象。
- 使用 observe() 方法将 Observer 对象附加到 LiveData 对象。observe() 方法会采用 LifecycleOwner 对象。这样会使 Observer 对象订阅 LiveData 对象,以使其收到有关更改的通知。通常情况下,您可以在界面控制器(如 activity 或 fragment)中附加 Observer 对象。
2,3可以合为一步
public class MainActivity extends AppCompatActivity {
// 第一步 创建LiveData实例并指定数据类型
private MutableLiveData<String> testLivedata = new MutableLiveData<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
TextView tv = findViewById(R.id.tv);
Button btn = findViewById(R.id.btn);
// 第二步 创建可定义 onChanged() 方法的 Observer 对象
Observer<String> observer = new Observer<String>() {
@Override
public void onChanged(String s) {
tv.setText(s);
}
};
//第三步 添加数据观察者
testLivedata.observe(this, observer);
/* 第二步和第三步合为一步
testLivedata.observe(this,new Observer<String>() {
@Override
public void onChanged(String s) {
tv.setText(s);
}
} );
*/
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testLivedata.setValue("这是Livedata发送的数据");
}
});
}
}
更新LiveData对象
LiveData
没有公开可用的方法来更新存储的数据。MutableLiveData
类将公开 setValue(T)
和 postValue(T)
方法,如果需要修改存储在 LiveData 对象中的值,则必须使用这些方法。通常情况下会在 ViewModel
中使用 MutableLiveData
,然后 ViewModel
只会向观察者公开不可变的 LiveData 对象。设置观察者关系后,您可以更新 LiveData 对象的值。
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
model.getCurrentName().setValue(anotherName);
//getCurrentName返回一个MutableLiveData对象。setValue方法改变值。
}
});
架构中的LiveData
LiveData
具有生命周期感知能力,遵循 activity
和 fragment
等实体的生命周期。使用 LiveData
在这些生命周期所有者和生命周期不同的其他对象(例如 ViewModel 对象)之间传递数据。ViewModel
的主要责任是加载和管理与界面相关的数据,因此非常适合作为用于保留LiveData
对象的备选方法。在 ViewModel
中创建 LiveData
对象,然后使用这些对象向界面层公开状态。activity
和 fragment
不应保留 LiveData 实例
,因为它们的用途是显示数据,而不是保持状态。
当 LiveData 对象具有活跃观察者时,会调用 onActive() 方法
当 LiveData 对象没有任何活跃观察者时,会调用 onInactive() 方法
因此可以继承LiveData然后根据情况重写。
转化LiveData
需要将 LiveData
对象分派给观察者之前对存储在其中的值进行更改,或者可能需要根据另一个实例的值返回不同的 LiveData
实例。Lifecycle
软件包会提供 Transformations
类,该类包括可应对这些情况的辅助程序方法。
对LiveData的值进行更改
Transformations.map()
对存储在 LiveData
对象中的值应用函数,并将结果传播到下游。
MutableLiveData<String> testMapLivedata
= (MutableLiveData<String>) Transformations.map(testLivedata,
new Function<String, String>() {
@Override
// 具体操作
public String apply(String input) {
return input + "Livedata Map";
}
});
// testMapLivedata注册观察者,testLiveData对象的变化会传播到下游
testMapLivedata.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
tv.setText(s);
}
});
//testLiveData的值发生变化
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testLivedata.setValue("这是Livedata发送的数据");
}
});
根据另一个实例的值返回不同的 LiveData 实例
Transformations.switchMap()
根据另一个实例的值返回不同的 LiveData 实例.
public class MainActivity extends AppCompatActivity {
// 第一步 创建LiveData实例并指定数据类型
private final MutableLiveData<Boolean> testLivedata = new MutableLiveData<Boolean>();
private final MutableLiveData<String> lv1 = new MutableLiveData<String>();
private final MutableLiveData<String> lv2 = new MutableLiveData<String>();
private boolean flag = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
TextView tv = findViewById(R.id.tv);
Button btn = findViewById(R.id.btn);
//根据不同的值切换不同的LiveData
MutableLiveData<String> switchMapLv =(MutableLiveData<String>)Transformations
.switchMap(testLivedata, new Function<Boolean,LiveData<String>>() {
@Override
public MutableLiveData<String> apply(Boolean input) {
return getLiveDataById(input);
}
});
// 设置观察者
switchMapLv.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
tv.setText(s);
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testLivedata.setValue(flag);
flag = !flag;
}
});
}
MutableLiveData<String> getLiveDataById(boolean flag){
lv1.setValue("this is LiveData1");
lv2.setValue("this is liveData2");
if (flag)
return lv1;
return lv2;
}
}