LiveData初识
LiveData
is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.
LiveData是一种类,持有可被观察的数据。
LiveData是一种可感知生命周期的组件,意味着该组件重视其他app组件的生命周期,如Activity、Fragment、Service,该组件能确保,仅仅在Activity\Fragment\Service等组件都处于活跃的生命周期的状态的时候,才去更新app组件。这里的活跃状态就是指处于start 和resume状态。也不用考虑Activity Fragment销毁时导致的内存泄漏问题,LiveData会自动解除与其的注册关系。LiveData可以在横竖屏切换等Configuration 改变时,也能保证获取到最新的数据。LiveData可以实现资源共享。
LiveData的基本使用
1、配置环境
打开AS新建一个工程,打开我们的app下的build.gradle 文件。添加如下依赖:
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.1"
// alternatively, just ViewModel
implementation "android.arch.lifecycle:viewmodel:1.1.1"
// alternatively, just LiveData
implementation "android.arch.lifecycle:livedata:1.1.1"
完整的截图如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.1"
defaultConfig {
applicationId "com.ekwing.livedatademo"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
dataBinding{
enabled=true
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:1.1.1"
// alternatively, just ViewModel
implementation "android.arch.lifecycle:viewmodel:1.1.1"
// alternatively, just LiveData
implementation "android.arch.lifecycle:livedata:1.1.1"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
注意我这里同时也使用了下Data Binding,就是这句了:
dataBinding{
enabled=true
}
2、创建测试的model
我们新建一个java bean类,让他继承自ViewModel如下所示:
public class TestViewModel extends ViewModel {
private MutableLiveData<String> mNameEvent=new MutableLiveData<>();//基本的数据姓名
private MutableLiveData<String> age=new MutableLiveData<>();//年龄
private MutableLiveData<String> year=new MutableLiveData<>();//年份
public MutableLiveData<String> getAge() {
return age;
}
public MutableLiveData<String> getmNameEvent() {
return mNameEvent;
}
public MutableLiveData<String> getYear() {
return year;
}
}
我们可以看到这里只有get方法,没有set方法,等会我们就知道为啥没有set方法了,这也是所谓的Live Data比较优秀的地方吧!
我们可以看到上面出现了一个MutableLiveData的类,我们来看下他的源码:
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
我们看到他是继承自LiveData的,里面有两个复写的方法,这两个方法之间的区别是, 调用 setValue 方法,Observer 的 onChanged 方法会在调用 setValue 方法的线程回调。而postvalue 方法,Observer 的 onChanged 方法将会在主线程回调。
LiveData
通常存储在ViewModel
之中, 并通过get方法
来获取,这也是为啥我们要继承自ViewModel,为什么将LiveData放置到ViewModel中,而不放到activity或者fragment中?这是为了避免fragment和activity的代码臃肿将LiveData和特定的activity/fragment解耦,能够在configuration改变的时候,LiveData依然存活。
3、在Activity中使用
写下Activity的布局:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/tv_show"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_show_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_show" />
<TextView
android:id="@+id/tv_show_third"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_show_second" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tv_show"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="20dp"
android:text="更新数据了"
android:id="@+id/bt_change"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
在activity的onCreate中写下如下代码:
mTestViewModel= ViewModelProviders.of(this).get(TestViewModel.class);//创建ViewModel 绑定activity
MutableLiveData<String> nameEvent=mTestViewModel.getmNameEvent();//创建注册更新UI的观察者
nameEvent.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
activityMainBinding.tvShow.setText(s);
}
});
MutableLiveData<String> year=mTestViewModel.getYear();
year.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
activityMainBinding.tvShowSecond.setText(s);
}
});
MutableLiveData<String> age=mTestViewModel.getAge();
age.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
activityMainBinding.tvShowThird.setText(s);
}
});
首先将我们写的ViewModel跟activity绑定,再为我们model里的各个字段创建观察者!
当数据发生改变的时候:
activityMainBinding.btChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTestViewModel.getmNameEvent().setValue("java");
mTestViewModel.getAge().setValue("20");
mTestViewModel.getYear().setValue("2019");
// String isMain=Looper.getMainLooper()==Looper.myLooper()?"主线程":"非主线程";
// Log.e("222222", "onClick: "+ isMain);
}
});
通过点击事件来改变数据。
整个Activity的代码如下:
public class MainActivity extends AppCompatActivity {
TestViewModel mTestViewModel;
ActivityMainBinding activityMainBinding;//数据绑定
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding= DataBindingUtil.setContentView(this,R.layout.activity_main);//数据绑定
mTestViewModel= ViewModelProviders.of(this).get(TestViewModel.class);//创建ViewModel
MutableLiveData<String> nameEvent=mTestViewModel.getmNameEvent();//创建注册更新UI的观察者
nameEvent.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
activityMainBinding.tvShow.setText(s);
}
});
MutableLiveData<String> year=mTestViewModel.getYear();
year.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
activityMainBinding.tvShowSecond.setText(s);
}
});
MutableLiveData<String> age=mTestViewModel.getAge();
age.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
activityMainBinding.tvShowThird.setText(s);
}
});
activityMainBinding.btChange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTestViewModel.getmNameEvent().setValue("java");
mTestViewModel.getAge().setValue("20");
mTestViewModel.getYear().setValue("2019");
// String isMain=Looper.getMainLooper()==Looper.myLooper()?"主线程":"非主线程";
// Log.e("222222", "onClick: "+ isMain);
}
});
}
}
这样当我们,数据发生变化的时候,数据会在UI上进行自动的更新。上面只是一个简单的使用,当然LiveData还有其它的用处。