Android--Jetpack的使用(一)

311 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

目录

1、ViewModel

2、ViewModel + LiveData

3、ViewModel + LiveData + dataBinding

4、ViewModel + SavedStateHandle + LiveData + dataBinding

5、例子下载

  参考文献


1、ViewModel

  ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存

例子:

在这里插入图片描述

代码:

MyVModel

import androidx.lifecycle.ViewModel;

public class MyVModel extends ViewModel {
    public int num=0;
}

MainActivity

//创建MyVModel
myVModel = AndroidViewModelFactory.getInstance(getApplication()).create(MyVModel.class);
//+1
myVModel.num++;
tv.setText(String.valueOf(myVModel.num));
//+2
myVModel.num += 2;
tv.setText(String.valueOf(myVModel.num));

2、ViewModel + LiveData

  LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

例子:

在这里插入图片描述

代码:

MyVModelWithLiveData

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MyVModelWithLiveData extends ViewModel {
    //创建LiveData对象
    private MutableLiveData<Integer> data;
    //创建get方法
    public MutableLiveData<Integer> getNum() {
        //当第一次get的时候初始化
        if (null == data) {
            data = new MutableLiveData<>();
            data.setValue(0);
        }
        return data;
    }
    //方法
    public void addNum(int a) {
        data.setValue(data.getValue() + a);

    }
}

MainActivity

//创建viewmodel
myVModelWithLiveData = AndroidViewModelFactory.getInstance(getApplication()).create(MyVModelWithLiveData.class);
//观察LiveData对象
myVModelWithLiveData.getNum().observe(this, new Observer<Integer>() {
    @Override
    public void onChanged(Integer integer) {
        //当监听到数据发生变化时跟新界面
        tv1.setText(String.valueOf(integer ));
    }
});

3、ViewModel+LiveData+dataBinding

  在原来的方法中,就是通过findviewById()的方法拿到TextView,然后通过setText方法把viewmodel中的numberTextView绑定到一块.

  在使用了dataBinding以后,就可以使用赋值表达式@{}来实现绑定,如下:

  <TextView
            android:text="@{String.valueOf(vmodel.number),default=0}" />
例子

在这里插入图片描述

代码

module的build.gradle

android {
   ...
   /*配置使用dataBinding*/
    buildFeatures {
        dataBinding true;
    }
    /*配置使用jdk1.8,因为会用到Lambda表达式*/
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

MyViewModel

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private MutableLiveData<Integer> number;
    //控制显隐
    private MutableLiveData<Boolean> isVisibiliy;

    public MutableLiveData<Integer> getNumber() {
        if (null == number) {
            number = new MutableLiveData<>();
            number.setValue(0);
        }
        return number;
    }

    public MutableLiveData<Boolean> getIsVisibiliy() {
        if (isVisibiliy == null) {
            isVisibiliy = new MutableLiveData<>();
            isVisibiliy.setValue(true);
        }
        return isVisibiliy;
    }

    public void setIsVisibiliy() {
        isVisibiliy.setValue(!isVisibiliy.getValue());
    }

    public void addNum(int num) {
        number.setValue(number.getValue() + num);
    }

}

布局文件

<?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>
        <!--导入View类-->
        <import type="android.view.View" />
        <variable
            name="vmodel"
            type="com.example.d0810.MyViewModel" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        tools:context=".MainActivity2">

        <TextView
            android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@{String.valueOf(vmodel.number),default=0}"
            android:textSize="30sp" />

        <Button
            android:id="@+id/btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->vmodel.addNum(1)}"
            android:text="+1" />

        <Button
            android:id="@+id/btn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->vmodel.addNum(2)}"
            android:text="+2" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:background="#000" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tv_v"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:text="文本"
                android:textSize="28sp"
                android:visibility="@{vmodel.isVisibiliy ? View.VISIBLE : View.INVISIBLE}" />

            <Button
                android:id="@+id/btn_v"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:onClick="@{() -> vmodel.setIsVisibiliy()}"
                android:text="控制显隐" />
        </LinearLayout>

    </LinearLayout>
</layout>

MainActivity2

public class MainActivity2 extends AppCompatActivity {
    private ActivityMain2Binding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyViewModel myViewModel = AndroidViewModelFactory.getInstance(getApplication()).create(MyViewModel.class);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main2);
        binding.setVmodel(myViewModel);
        //
        binding.setLifecycleOwner(this);
    }
}

4、ViewModel的SavedStateHandle

  当程序推出到后台的时候,然后被手机系统回收导致的进程终止,在原来的方式是使用 onSaveInstanceState()方法来进行保存数据和状态。

  所以在 ViewModel的构造函数的时候会接收一个 SavedStateHandle 对象,这是一个键值对映射,用户保存状态。

注意: 状态必须是简单的轻量级状态。对于复杂或大型数据,您应该使用本地持久性存储。

SavedStateHandle所有的方法
  • get(String key) :根据键值来获取数组
  • contains(String key):判断handle中是否包含key这个键
  • remove(String key):根据键值删除数据
  • set(String key, T value):保存数据
  • keys():获取所有的键值
  • getLiveData(String key):返回封装在LiveData可观察对象中的值。
例子效果图

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

SavedStateHandle的使用

 ScoreVmodel

public class ScoreVmodel extends ViewModel {
    public final String ASCORE = "aScore";
    public final String BSCORE = "bScore";
    public final String AUNDOSCORE = "aUndoScore";
    public final String BUNDOSCORE = "bUndoScore";
//保存状态模块
private SavedStateHandle handle;
public ScoreVmodel(SavedStateHandle handle) {
    this.handle = handle;
}

    //获取A队的分数
    public MutableLiveData<Integer> getaScore() {
        if (!handle.contains(ASCORE)) {
            handle.set(ASCORE, 0);
        }
        return handle.getLiveData(ASCORE);
    }

    //获取B队的分数
    public MutableLiveData<Integer> getbScore() {
        if (!handle.contains(BSCORE)) {
            handle.set(BSCORE, 0);
        }
        return handle.getLiveData(BSCORE);
    }

    //添加A队的分数
    public void addAScore(int s) {
        //首先把A队和B队的分数保存起来
        handle.set(AUNDOSCORE, getaScore().getValue());
        handle.set(BUNDOSCORE, getbScore().getValue());
        getaScore().setValue(getaScore().getValue() + s);
    }

    //添加B队的分数
    public void addBScore(int s) {
        //首先把A队和B队的分数保存起来
        handle.set(AUNDOSCORE, getaScore().getValue());
        handle.set(BUNDOSCORE, getbScore().getValue());
        //再计算分数
        getbScore().setValue(getbScore().getValue() + s);
    }

    public void reset() {
        //首先把A队和B队的分数保存起来
        handle.set(AUNDOSCORE, getaScore().getValue());
        handle.set(BUNDOSCORE, getbScore().getValue());
        handle.set(ASCORE, 0);
        handle.set(BSCORE, 0);
    }

    //撤回一次
    public void undoScore() {
        handle.set(ASCORE, handle.getLiveData(AUNDOSCORE).getValue());
        handle.set(BSCORE, handle.getLiveData(BUNDOSCORE).getValue());
    }
}

 ScoreActivity

public class ScoreActivity extends AppCompatActivity {
    private ActivityScoreBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_score);
        ScoreVmodel vmodel = new ViewModelProvider(this, new SavedStateViewModelFactory(getApplication(), this)).get(ScoreVmodel.class);
        binding.setModel(vmodel);
        /**
         * 这句话时必须要加上的,这个方法的注释如下
         *   Sets the {@link LifecycleOwner} that should be used for observing changes of
         *   LiveData in this binding. If a {@link LiveData} is in one of the binding expressions
         *   and no LifecycleOwner is set, the LiveData will not be observed and updates to it
         *   will not be propagated to the UI.
         * 我理解的大概意思就是 这个方法就是把 LifecycleOwner 和 LiveData 绑定到一块,只有绑定到一块。当
         * 数据发生变化的时候 才会更新UI界面
         */
        binding.setLifecycleOwner(this);
    }
}

 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="model"
            type="com.example.d0810.score.ScoreVmodel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".score.ScoreActivity">

        <TextView
            android:id="@+id/tv_ta"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/a"
            android:textColor="@color/teamAColor"
            android:textSize="@dimen/teamSizeText"
            app:layout_constraintBottom_toTopOf="@+id/guideline2"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline2" />

        <TextView
            android:id="@+id/tv_tb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/b"
            android:textColor="@color/teamBColor"
            android:textSize="@dimen/teamSizeText"
            app:layout_constraintBottom_toTopOf="@+id/guideline2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="@+id/guideline2" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            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/guideline2"
            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/guideline3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.2" />

        <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.35" />

        <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.5" />

        <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.65" />

        <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.75" />

        <TextView
            android:id="@+id/tv_ascore"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(model.getaScore()),default=@string/zero}"
            android:textColor="@color/teamAColor"
            android:textSize="@dimen/scoreTextSize"
            app:layout_constraintBottom_toTopOf="@+id/guideline3"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline3" />

        <TextView
            android:id="@+id/tv_bscore"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(model.getbScore()),default=@string/zero}"
            android:textColor="@color/teamBColor"
            android:textSize="@dimen/scoreTextSize"
            app:layout_constraintBottom_toTopOf="@+id/guideline3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.504"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="@+id/guideline3" />

        <Button
            android:id="@+id/btn_a1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/teamAColor"
            android:onClick="@{() -> model.addAScore(1) }"
            android:text="@string/add1"
            android:textColor="@android:color/white"
            android:textSize="30sp"
            app:layout_constraintBottom_toTopOf="@+id/guideline4"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline4" />

        <Button
            android:id="@+id/btn_a2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/teamAColor"
            android:onClick="@{() -> model.addAScore(2) }"
            android:text="@string/add2"
            android:textColor="@android:color/white"
            android:textSize="@dimen/btnTextsize"
            app:layout_constraintBottom_toTopOf="@+id/guideline5"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline5" />

        <Button
            android:id="@+id/btn_a3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/teamAColor"
            android:onClick="@{() -> model.addAScore(3) }"
            android:text="@string/add3"
            android:textColor="@android:color/white"
            android:textSize="@dimen/btnTextsize"
            app:layout_constraintBottom_toTopOf="@+id/guideline6"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline6" />

        <Button
            android:id="@+id/btn_b3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/teamBColor"
            android:onClick="@{() -> model.addBScore(3) }"
            android:text="@string/add3"
            android:textColor="@android:color/white"
            android:textSize="@dimen/btnTextsize"
            app:layout_constraintBottom_toTopOf="@+id/guideline6"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="@+id/guideline6" />

        <Button
            android:id="@+id/btn_b2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/teamBColor"
            android:onClick="@{() -> model.addBScore(2)}"
            android:text="@string/add2"
            android:textColor="@android:color/white"
            android:textSize="@dimen/btnTextsize"
            app:layout_constraintBottom_toTopOf="@+id/guideline5"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="@+id/guideline5" />

        <Button
            android:id="@+id/btn_b1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/teamBColor"
            android:onClick="@{() -> model.addBScore(1) }"
            android:text="@string/add1"
            android:textColor="@android:color/white"
            android:textSize="@dimen/btnTextsize"
            app:layout_constraintBottom_toTopOf="@+id/guideline4"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="@+id/guideline4" />

        <ImageButton
            android:id="@+id/ibtn_undo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/undo"
            android:onClick="@{() -> model.undoScore() }"
            app:layout_constraintEnd_toStartOf="@+id/guideline"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/guideline7"
            app:srcCompat="@drawable/ic_baseline_undo_24" />

        <ImageButton
            android:id="@+id/ibtn_reset"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/reset"
            android:onClick="@{() -> model.reset()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="@+id/guideline7"
            app:srcCompat="@drawable/ic_baseline_loop_24" />

        <View
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="2dp"
            android:layout_marginBottom="5dp"
            android:background="@android:color/darker_gray"
            app:layout_constraintBottom_toTopOf="@+id/guideline7"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

5、例子下载

download.csdn.net/download/lj…

参考文献

[1] Android开发教程(2019最新版,使用JetPack)
[2] Android官方的开发文档