Android  JetPack~ LiveData (一)   介紹與使用

TMusketeer發表於2023-02-16
一般情況下LiveData都是搭配這ViewModel使用,這裡先介紹一下LiveData,再結合ViewModel使用
 

1、什麼是LiveData

  1. LiveData是一個觀察者模式的資料實體類,它可以在所有註冊觀察者回撥裡檢視資料是否有更新。
  2. LiveData它能感知繫結者的生命週期(如Activity,Fragment),不會發生記憶體洩露,因為它只會給活躍狀態的activity回撥,我們在使用的時候通常都會在回撥裡去更新UI。
  3. 從非活躍狀態變為活躍狀態時,回撥方法會立即接收到最新的資料
  4. 當裝置切橫豎屏,會重建Activity生命週期,它也會立即接收最新的可用資料。
  5. 不可變,setValue和postValue不支援外部使用(protected修飾)。下面程式碼講解
  6. 抽象類,無法直接new
 

2、什麼是MutableLiveData

  1. MutableLiveData的父類是LiveData
  2. 用法和LiveData類似,也是在註冊觀察者回撥裡檢視更新資料
  3. 可變,setValue和postValue支援外部使用(public修飾)
  4. 普通類,可以直接new
 

3、LiveData與MutableLiveData區別

  1. LiveData在實體類裡可以通知指定某個欄位的資料更新.(下面會貼程式碼)
  2. MutableLiveData則是完全是整個實體類或者資料型別變化後才通知.不會細節到某個欄位
 

4、LiveData的使用

public class UserBean extends LiveData<UserBean> {
    String name;
    int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        postValue(this);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        postValue(this);

    }
}
postValue(this);這個方法是用於觸發回撥資料更新的方法. 你可以在你需要被觀察的資料裡新增.
 
小注意點:如果不使用postValue(this)會怎麼樣?
    public void setAge(int age) {
        this.age = age;
//        postValue(this);
// 如果不寫的話,單獨呼叫setAge後,在外getAge獲取不到值,因為回撥沒有被觸發,
// 如果name寫了postValue(this),更新了name也會連著age更新,因為傳的是this
    }
你也可以整合LiveData<String>,那麼postValue(string),回撥中只會接收postValue最後的賦值。
 

4.1ViewModel新建

public class MyViewModel extends ViewModel {
    
    public UserBean mUserBean = new UserBean();

    public UserBean getUserBean() {
        return mUserBean;
    }
    
}
 

4.2Activity中新增回撥方法

//透過ViewModeProvider 把activity和ViewModel繫結起來。
myViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
observer = new Observer<UserBean>() {
    @Override
    public void onChanged(UserBean userBean) {
        Log.e("activity",userBean.getName());
        mBinding.textShow.setText("name="+userBean.getName()+"  ,, age="+userBean.getAge()+"");
    }
};
//繫結觀察者
myViewModel.getUserBean().observe(this, observer);

a = 0;
mBinding.btnUpdata.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        myViewModel.getUserBean().setName("大王"+a);
        myViewModel.getUserBean().setAge(a++);
    }
});
注意:這裡的myViewModel.getUserBean().observe() 是LiveData的方法。
我們上面建立了一個Observer,並且和activity關聯,然後透過一個按鈕去動態設定值,果然回撥裡就會有資料更新。
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
 

4.3有繫結就會有解綁

myViewModel.getUserBean().removeObserver(observer);
 

5、MutableLiveData的使用

它是直接作用在變數上,mStr.setValue(s);觸發觀察者的回撥。
public class MyViewModel extends ViewModel {
    private MutableLiveData<String> mStr;

    public MutableLiveData<String> getmStr() {
        return mStr;
    }

    public void setmStr(String s) {
        if(mStr==null){
            mStr = new MutableLiveData<>();
        }
        mStr.setValue(s);
    }

}

5.1在activity中使用

myViewModel.getmStr().observe(this, new Observer<String>() {
    @Override
    public void onChanged(String s) {
        
    }
});
 

6、LiveData和MutableLiveData的可變與不可變

其實就是setValue和postValue是否暴露問題,LiveData中是不支援外部使用,而MutableLiveData特意放開
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}
 
可以看到在MutableLiveData包裹的有setValue,postValue方法
Android  JetPack~ LiveData (一)   介紹與使用
當然我們也可以讓它不對外暴露setValue,postValue方法,返回值修改為LiveData<String>
public class MyViewModel extends ViewModel {
    private MutableLiveData<String> mStr= new MutableLiveData<>();

    public LiveData<String> getmStr() {
        return mStr;
    }
    //在外面只能透過這種方式去更新
    public void setmStr(String s) {
        mStr.setValue(s);
}
}
Android  JetPack~ LiveData (一)   介紹與使用

7、其他方法

postValue()
  postValue的特性如下:
  1.此方法可以在其他執行緒中呼叫
  2.如果在主執行緒執行釋出的任務之前多次呼叫此方法,則僅將分配最後一個值。
  3.如果同時呼叫 .postValue()和.setValue(),結果是post的值覆蓋set值。

setValue()
  setValue()的特性如下:
  1.此方法只能在主執行緒裡呼叫
getValue()
  返回當前值。 注意,在後臺執行緒上呼叫此方法並不能保證將接收到最新的值。 
  
removeObserver(@NonNull final Observer<? super T> observer) 
    移除指定的觀察者
    
removeObservers(@NonNull final LifecycleOwner owner)
  移除當前Activity或者Fragment的全部觀察者
  
hasActiveObservers()
  如果此LiveData具有活動(Activity或者Fragment在前臺,當前螢幕顯示)的觀察者,則返回true。其實如果這個資料的觀察者在最前臺就返回true,否則false。

hasObservers()
  如果此LiveData具有觀察者,則返回true。
 
observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
  設定此LiveData資料當前activity或者Fragment的觀察者,會給此activity或者Fragment在前臺時回撥資料。
 
observeForever(@NonNull Observer<? super T> observer)
  1.設定永遠觀察者,永遠不會被自動刪除。您需要手動呼叫removeObserver(Observer)以停止觀察此LiveData,
  2.設定後此LiveData,一直處於活動狀態,不管是否在前臺哪裡都會獲得回撥。

總結:

LiveData一般使用在實體類,MutableLiveData作用在變數上,他們通常和ViewModel結合使用,上面例子過於簡單,工作當中可按照業務需要進行調整。
 

相關文章