原文链接https://www.shanya.world/archives/266bf90b.html
ViewModel可以将数据模块进行单独的管理,可以使我的控制器更加的简单,只需要专注于控制界面的逻辑和用户的操作。另外当我们的Activity被Destroy或者重新Create时数据不会丢失。(例如切换系统语言、屏幕旋转)其配合LiveData可以对数据的改变进行监听。然后通过DataBingding将数据与控件进行绑定,减少像按键响应等代码的数量。
这里我将一个篮球赛计分的例子来记录ViewModel、LivaData、DataBinding的用法
首先新建一个 MyViewModel 继承于 ViewModel。
package com.shanya.score;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> aTeamScore; //a队的分数
private MutableLiveData<Integer> bTeamScore; //b队的分数
private int aBack,bBack; //用于Undo操作的上一次各队分数
//普通的Get方法
public MutableLiveData<Integer> getaTeamScore() {
if (aTeamScore == null){ //处理空指针异常
aTeamScore = new MutableLiveData<>();
aTeamScore.setValue(0);
}
return aTeamScore;
}
public MutableLiveData<Integer> getbTeamScore() {
if (bTeamScore == null){
bTeamScore = new MutableLiveData<>();
bTeamScore.setValue(0);
}
return bTeamScore;
}
//加分操作,该方法通过DataBinding与按键绑定
public void aTeamAdd(int p){
aBack = aTeamScore.getValue();
bBack = bTeamScore.getValue();
aTeamScore.setValue(aTeamScore.getValue() + p);
}
public void bTeamAdd(int p){
aBack = aTeamScore.getValue();
bBack = bTeamScore.getValue();
bTeamScore.setValue(bTeamScore.getValue() + p);
}
//重置操作
public void reset(){
aBack = aTeamScore.getValue();
bBack = bTeamScore.getValue();
aTeamScore.setValue(0);
bTeamScore.setValue(0);
}
//撤销操作
public void undo(){
aTeamScore.setValue(aBack);
bTeamScore.setValue(bBack);
}
}
接下来就说一说DataBinding是怎么与控件进行绑定的。
首先,我们需在app目录下的build.gradle里面打开DataBinding
之后打开我们的布局文件,切换到Text页面
光标放在图中的位置并点击灯泡图标
选择第一个
之后在<data> <data>中间加一个变量,这里直接贴出我的xml文件
<?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>
<variable
name="data"
type="com.shanya.score.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.05" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.15" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.35" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.65" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.9" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/team_a"
android:textSize="@dimen/mid_font"
app:layout_constraintBottom_toTopOf="@+id/guideline5"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/team_b"
android:textSize="@dimen/mid_font"
app:layout_constraintBottom_toTopOf="@+id/guideline5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
<TextView
android:id="@+id/textViewScoreA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(data.getaTeamScore())}"
android:textColor="@color/colorAccent"
android:textSize="@dimen/large_font"
app:layout_constraintBottom_toTopOf="@+id/guideline6"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline5"
tools:text="120" />
<TextView
android:id="@+id/textViewScoreB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(data.getbTeamScore())}"
android:textColor="@color/colorPrimary"
android:textSize="@dimen/large_font"
app:layout_constraintBottom_toTopOf="@+id/guideline6"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/guideline5"
tools:text="20" />
<Button
android:id="@+id/buttonA1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#E91E63"
android:text="@string/add1"
android:textColor="@android:color/background_light"
android:textSize="@dimen/big_font"
android:onClick="@{()->data.aTeamAdd(1)}"
app:layout_constraintBottom_toTopOf="@+id/guideline7"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline6" />
<Button
android:id="@+id/buttonB1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@color/colorPrimary"
android:text="@string/add1"
android:textColor="@android:color/background_light"
android:textSize="@dimen/big_font"
android:onClick="@{()->data.bTeamAdd(1)}"
app:layout_constraintBottom_toTopOf="@+id/guideline7"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/guideline6" />
<Button
android:id="@+id/buttonA2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#E91E63"
android:text="@string/add2"
android:textColor="@android:color/background_light"
android:textSize="@dimen/big_font"
android:onClick="@{()->data.aTeamAdd(2)}"
app:layout_constraintBottom_toTopOf="@+id/guideline8"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline7" />
<Button
android:id="@+id/buttonB2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@color/colorPrimary"
android:text="@string/add2"
android:textColor="@android:color/background_light"
android:textSize="@dimen/big_font"
android:onClick="@{()->data.bTeamAdd(2)}"
app:layout_constraintBottom_toTopOf="@+id/guideline8"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/guideline7" />
<Button
android:id="@+id/buttonA3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="#E91E63"
android:text="@string/add3"
android:textColor="@android:color/background_light"
android:textSize="@dimen/big_font"
android:onClick="@{()->data.aTeamAdd(3)}"
app:layout_constraintBottom_toTopOf="@+id/guideline9"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline8" />
<Button
android:id="@+id/buttonB3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@color/colorPrimary"
android:text="@string/add3"
android:textColor="@android:color/background_light"
android:textSize="@dimen/big_font"
android:onClick="@{()->data.bTeamAdd(3)}"
app:layout_constraintBottom_toTopOf="@+id/guideline9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/guideline8" />
<ImageView
android:id="@+id/imageViewUndo"
android:layout_width="50dp"
android:layout_height="50dp"
android:contentDescription="@string/pictrue"
android:onClick="@{()->data.undo()}"
app:layout_constraintBottom_toTopOf="@+id/guideline10"
app:layout_constraintEnd_toStartOf="@+id/guideline3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline9"
app:srcCompat="@drawable/ic_redo_black_24dp" />
<ImageView
android:id="@+id/imageViewRefresh"
android:layout_width="50dp"
android:layout_height="50dp"
android:contentDescription="@string/pictrue"
android:onClick="@{()->data.reset()}"
app:layout_constraintBottom_toTopOf="@+id/guideline10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline3"
app:layout_constraintTop_toTopOf="@+id/guideline9"
app:srcCompat="@drawable/ic_refresh_black_24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
之后就是MainActivity里面的操作了
package com.shanya.score;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import android.database.DatabaseUtils;
import android.os.Bundle;
import com.shanya.score.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);//相当于上面注释的那一条语句
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);//创建MyViewModel实例
binding.setData(myViewModel);
binding.setLifecycleOwner(this);
}
}
可以发现以前的各种控件代码都不见了。代码更加的精简。