Android 开发 ViewModel、LiveData、DataBinding 的一个联合使用

原文链接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
Android 开发 ViewModel、LiveData、DataBinding 的一个联合使用_第1张图片

之后打开我们的布局文件,切换到Text页面
光标放在图中的位置并点击灯泡图标
在这里插入图片描述
选择第一个
Android 开发 ViewModel、LiveData、DataBinding 的一个联合使用_第2张图片
之后在 中间加一个变量,这里直接贴出我的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);
    }
}

可以发现以前的各种控件代码都不见了。代码更加的精简。

Demo源码下载地址GitHub 或者 CSDN

你可能感兴趣的:(Android)