ViewModel、LiveData、Databinding

1.ViewModel
ViewModel 可以用作儲(chǔ)存界面數(shù)據(jù),取代Bundle savedInstanceState存儲(chǔ)數(shù)據(jù)。ViewModel就是一個(gè)存儲(chǔ)著我們界面數(shù)據(jù)的類,界面數(shù)據(jù)的設(shè)定全部來(lái)自自定義的ViewModel。

首先,我們需要對(duì)某一個(gè)界面(例如:MainActivity)設(shè)定一個(gè)ViewModel(Demo中使用的是MyViewModel 繼承自 ViewModel)

我需要對(duì)每一個(gè)界面定義一個(gè)專屬的ViewModel,這樣易于維護(hù),且代碼較為美觀;
ViewModel的包為androidx.lifecycle.ViewModel
MainActivity 需要引用包androidx.lifecycle.ViewModelProviders,注意ViewModelProviders后需要有"s",使用時(shí)需要添加依賴implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
import androidx.lifecycle.ViewModel;

class MyViewModel extends ViewModel {

private int textViewContent = 0;

int getTextViewContent() {
    return textViewContent;
}

void setTextViewContent(int textViewContent) {
    this.textViewContent = textViewContent;
}

}
接著我們?cè)贛ainActivity中聲明和使用我們針對(duì)于該Activity創(chuàng)建的ViewModel

//獲取ViewModel類的對(duì)象
MyViewModel myViewModel;

//在onCreate()方法中獲取ViewModel的具體內(nèi)容
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
也就是說(shuō)以后我們?cè)诮o控件賦值時(shí)只需要獲取ViewModel實(shí)例中的數(shù)值即可,修改數(shù)值也是直接修改ViewModel中對(duì)應(yīng)的數(shù)值

//修改數(shù)值為當(dāng)前 textViewContent + 1
myViewModel.setTextViewContent(myViewModel.getTextViewContent() + 1);

//給控件賦值為 textViewContent + 1
textView.setText(String.valueOf(myViewModel.getTextViewContent()));

//為了保證每次界面銷毀重啟后,都可以保存之前的值,我們需要在onCreate()中,給控件賦值為 textViewContent
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
textView = findViewById(R.id.text);
textView.setText(String.valueOf(myViewModel.getTextViewContent()));
}
2、LiveData
LiveData的作用是讓底層數(shù)據(jù)更新時(shí),自動(dòng)更新界面控件視圖,減少手動(dòng)setText()

同樣作為視圖數(shù)據(jù)管理的一個(gè)類,LiveData寫在ViewModel類中。將被管理的值放于MutableLiveData<>容器中

注意MyViewModel類和MyViewModel類的聲明需要是public
注意拓展MutableLiveData<>容器中可以存放多種數(shù)據(jù)類型List<>、String等等
需要提供修改參數(shù)的方法
public class MyViewModel extends ViewModel {

private MutableLiveData<Integer> textViewContent;
public MyViewModel(){
    textViewContent = new MutableLiveData<>();
    textViewContent.setValue(0);
}

MutableLiveData<Integer> getTextViewContent() {
    if (textViewContent == null) {
        textViewContent = new MutableLiveData<>();
        textViewContent.setValue(0);
    }
    return textViewContent;
}

void addTextViewContent(int n) {
    textViewContent.setValue(textViewContent.getValue() + n);
}

}

接著在MainActivity中聲明控件、聲明ViewModel管理類、綁定ViewModel管理類、設(shè)置LiveData觀察者

點(diǎn)擊事件由直接設(shè)置控件值變?yōu)樵O(shè)置ViewModel對(duì)應(yīng)屬性值
控件屬性值通過(guò)觀察者的onChanged()方法設(shè)置
代碼和視圖分離,代碼結(jié)構(gòu)更加清晰

public class MainActivity extends AppCompatActivity {

//聲明控件
MyViewModel myViewModel;
Button button1, button2;
TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //綁定視圖
    setContentView(R.layout.activity_main);

    //找到控件
    textView = findViewById(R.id.text1);
    button1 = findViewById(R.id.button2);
    button2 = findViewById(R.id.button);

    //綁定ViewModel管理類
    myViewModel = ViewModelProviders.of(this).get(MyViewModelTest.class);

    //設(shè)置ViewModel觀察者
    myViewModel.getTextViewContent().observe(this, new Observer<Integer>() {
        @Override
        public void onChanged(Integer integer) {
            textView.setText(String.valueOf(integer));
        }
    });

    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            myViewModel.addTextViewContent(1);
        }
    });

    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            myViewModel.addTextViewContent(2);
        }
    });
}

}
3、Data Binding
將數(shù)據(jù)和View綁定,減少聲明控件、減少找到控件的過(guò)程

data Binding的使用和聲明涉及到build.gradle、Java、xml三個(gè)部分。

首先在build.gradle中打開dataBinding的開關(guān)

dataBinding{
    enabled=true
}

接下來(lái)完成Java部分的ViewModel的創(chuàng)建

public class MyViewModel extends ViewModel {

private MutableLiveData<Integer> textViewContent;

public MyViewModel(){
    textViewContent = new MutableLiveData<>();
    textViewContent.setValue(0);
}

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

public void addTextViewContent(int n) {
    textViewContent.setValue(textViewContent.getValue() + n);
}

}

在MainActivity中進(jìn)行控件的綁定、聲明

由于在build.gradle中打開了dataBinding的開關(guān),那么我們可以在MainActivity中獲取一個(gè)類ActivityMainBinding,這個(gè)是動(dòng)態(tài)生成的,名稱的組合為res-layout-activity_main.xml中.xml文件的名字加上Binding。

binding.setMyViewModel(myViewModel)中的MyViewModel,需要和xml文件中的name屬性相對(duì)應(yīng)
public class MainActivity extends AppCompatActivity {

MyViewModel myViewModel;
//聲明綁定的xml文件
ActivityMainBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //綁定xml視圖文件
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    //綁定ViewModel管理類
    myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    //聲明屬性(該屬性與xml文件中設(shè)置的數(shù)據(jù)name相對(duì)應(yīng))
    binding.setMyViewModel(myViewModel);
    //聲明視圖生命周期擁有者
    binding.setLifecycleOwner(this);
}

}
最后修改xml文件內(nèi)容

使用layout標(biāo)簽包裹整個(gè)xml文件
添加data標(biāo)簽
在data標(biāo)簽中添加variable標(biāo)簽來(lái)規(guī)定使用的數(shù)據(jù)名、綁定的ViewModel
在xml文件中設(shè)置text的屬性內(nèi)容
變量的使用格式為@{name.變量名(可能需要在其中做一些類型轉(zhuǎn)換)}
函數(shù)的使用格式為@{()->name.函數(shù)(包括參數(shù))}
<?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="myViewModel"
        type="com.code.databingdingdemo.MyViewModel" />
</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:text="@{String.valueOf(myViewModel.textViewContent)}"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.479"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.341" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="356dp"
        android:onClick="@{()->myViewModel.addTextViewContent(1)}"
        android:text="+1"
        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.116" />

</androidx.constraintlayout.widget.ConstraintLayout>

</layout>

原文鏈接:http://www.itdecent.cn/p/b35b387ee8d5

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容