前言:
Jetpack網上一搜全都有解釋,在這裏我就不介紹Jetpack了,直接給 ViewModel、LiveData、DataBinding上例子。
注:本文基於AndroidX的項目,本人自己理解的意思做的講解,有不對或疑惑的地方歡迎評論留言一起學習探討。
一、ViewModel:
1、功能:屏幕旋轉或者字號改變的時候該Activity數據不會丟失。
2、做法:寫一個類繼承ViewModel:
public class MyViewModel extends ViewModel {
private int number;
public int getNumber() {
return number;
}
public void addNumber(int number) {
this.number += number;
}
}
3、Activity中:
public class MainActivity extends AppCompatActivity {
private MyViewModel viewModel ;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.textView);
viewModel = new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MyViewModel.class);
tv.setText(String.valueOf(viewModel.getNumber()));
findViewById(R.id.button).setOnClickListener(v -> {
//可以給個事件來點擊然後這個數值就加2
viewModel.addNumber(2);
tv.setText(String.valueOf(viewModel.getNumber()));
});
此處需要注意,網上的教程甚至官網的教程給viewModel賦值的時候都是用的ViewModelProviders.of(this).get()的方法,但是這個方法已經淘汰了,所以得自己構建這樣一個函數,然後又會發現ViewModelProvider(this)這個構造函數並不存在,只有兩個參數的構造函數,ctrl+鼠標移到ViewModelProvider上面,可以發現需要一個傳一個工廠參數,所以就有了上面這個寫法。
二、LiveData:
1、作用:顧名思義,實時數據,就是數據發生改變的時候,它能自己去修改UI上面上的數據。比如上面我們點擊按鈕之後還需要手動去給這個textView重新setText。有了這個LiveData,我們就不用每次都給它重新設置值了。
2、做法:在上面這個MyViewModel中做修改:
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> number;
public MutableLiveData<Integer> getNumber() {
if (number == null) {
number = new MutableLiveData<>();
number.setValue(0);
}
return number;
}
public void addNumber(int number) {
this.number.setValue(getNumber().getValue() + number);
}
}
注意:MutableLiveData<這裏可以是其他bean對象,但是不能是view或者帶Context的東西,因爲viewModel的生命週期比Activity或者Fragment長>
3、Activity中給這個數據添加監聽:
public class MainActivity extends AppCompatActivity {
private MyViewModel viewModel ;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.textView);
viewModel = new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MyViewModel.class);
tv.setText(String.valueOf(viewModel.getNumber()));
//這裏添加監聽
viewModel.getNumber().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
tv.setText(String.valueOf(integer));
}
});
findViewById(R.id.button).setOnClickListener(v -> {
viewModel.addNumber(2);
//這裏去掉了tv的setText
});
//或者再有其他按鈕也同理只做加減不做賦值
findViewById(R.id.button2).setOnClickListener(v -> {
viewModel.addNumber(-2);
});
三、DataBinding:
1、作用:數據綁定,有了它,就不用findviewbyid了,甚至你可以不用在Activity裏面做setText和setOnClickListener。
2、做法:
2.1、app的build.gradle裏面添加一個聲明:
android {
......
defaultConfig {
......
//下面這個添加上
dataBinding{
enabled true
}
}
......
}
2.2、layout裏面的activity_main裏面,鼠標移到<?xml version="1.0" encoding="utf-8"?>左邊,會有一個燈泡,點擊下來點擊有data binding字樣的那句話,就會得到一個layout的根標籤:
<?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:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.259" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.44" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.629" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3、這個layout生成了之後它會自動生成一個以這個layout名字命名的類,比如這裏是activity_main,就會生成一個ActivityMainBinding的類,然後我們在Activity中使用它:
public class MainActivity extends AppCompatActivity {
private MyViewModel viewModel ;
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
//注意此處把上面這個設置界面的方式換成下面這個,並且賦值給binding
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
//然後就可以直接用binding.控件id 來表示該控件。
viewModel = new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MyViewModel.class);
viewModel.getNumber().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
//binding.textView表示原先tv對象了
binding.textView.setText(String.valueOf(integer));
}
});
//binding.button代替原先button
binding.button.setOnClickListener(v -> {
viewModel.addNumber(2);
});
binding.button2.setOnClickListener(v -> {
viewModel.addNumber(-2);
});
}
4、這只是初級形態,我們還有個高級一點的。第2步中生成了的layout中有一對標籤沒有使用,就是<data />標籤對。下面我們來使用:
4.1、把viewModel對象搬移到layout的data標籤中:
<data>
<variable
name="viewModel"
type="com.xaehu.jetpackstudy.MyViewModel" />
</data>
4.2、把setText和setOnClickListener搬到layout中:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(viewModel.number)}"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button1"
android:onClick="@{v -> viewModel.addNumber(2)}" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button2"
android:onClick="@{v -> viewModel.addNumber(-2)}"/>
可以看到,格式是“@{}”的形式,裏面就是java代碼或者landau表達式。
4.3、然後修改Activity中代碼,可以說是簡潔到飛起了:
public class MainActivity extends AppCompatActivity {
private MyViewModel viewModel ;
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
viewModel = new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MyViewModel.class);
binding.setViewModel(viewModel); //給layout設置data標籤的值
binding.setLifecycleOwner(this); //這句不能漏,否則不會生效
}
以上就是對ViewModel、LiveData、DataBinding的簡單使用。